@suveren/gateway 0.8.7 → 0.10.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.
- package/README.md +33 -1
- package/bin/suveren-gateway.js +363 -9
- package/content/integrations/erp.json +184 -0
- package/content/integrations/index.json +2 -1
- package/dist/control-plane/index.mjs +835 -118
- package/dist/mcp-server/http.mjs +876 -193
- package/dist/ui/assets/{index-tzStUGuj.js → index-B1qNl7zo.js} +21 -21
- package/dist/ui/index.html +1 -1
- package/lib/as-pairing.mjs +77 -0
- package/lib/config.d.mts +37 -0
- package/lib/config.mjs +198 -0
- package/node_modules/@hap/core/dist/index.d.mts +33 -2
- package/node_modules/@hap/core/dist/index.d.ts +33 -2
- package/node_modules/@hap/core/dist/index.js +26 -2
- package/node_modules/@hap/core/dist/index.mjs +25 -2
- package/node_modules/@hap/core/package.json +1 -1
- package/node_modules/@hap/core/src/gatekeeper.ts +36 -2
- package/node_modules/@hap/core/src/types.ts +21 -1
- package/node_modules/@hono/node-server/README.md +21 -10
- package/node_modules/@hono/node-server/dist/early-hints.cjs +1 -1
- package/node_modules/@hono/node-server/dist/early-hints.mjs +1 -1
- package/node_modules/@hono/node-server/dist/index.cjs +41 -19
- package/node_modules/@hono/node-server/dist/index.mjs +42 -20
- package/node_modules/@hono/node-server/dist/serve-static.cjs +1 -0
- package/node_modules/@hono/node-server/dist/serve-static.d.cts +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.d.mts +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.mjs +1 -0
- package/node_modules/@hono/node-server/package.json +3 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.d.ts +43 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.js +26 -5
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts +11 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js +96 -14
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.d.ts +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.js +11 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.js +6 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.d.ts +3 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js +12 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.d.ts +43 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.js +26 -5
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts +11 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js +96 -14
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.d.ts +1 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.js +11 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/server/demoInMemoryOAuthProvider.d.ts +2 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/server/demoInMemoryOAuthProvider.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.js +6 -3
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.d.ts +3 -0
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.d.ts.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js +12 -2
- package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js.map +1 -1
- package/node_modules/@modelcontextprotocol/sdk/package.json +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/crypto.d.ts +2 -2
- package/node_modules/@types/node/dgram.d.ts +1 -1
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/hono/dist/_virtual/_rolldown/runtime.js +13 -0
- package/node_modules/hono/dist/adapter/aws-lambda/conninfo.js +42 -23
- package/node_modules/hono/dist/adapter/aws-lambda/handler.js +318 -344
- package/node_modules/hono/dist/adapter/aws-lambda/index.js +2 -8
- package/node_modules/hono/dist/adapter/aws-lambda/types.js +1 -0
- package/node_modules/hono/dist/adapter/bun/conninfo.js +20 -25
- package/node_modules/hono/dist/adapter/bun/index.js +3 -13
- package/node_modules/hono/dist/adapter/bun/serve-static.js +27 -27
- package/node_modules/hono/dist/adapter/bun/server.js +11 -5
- package/node_modules/hono/dist/adapter/bun/ssg.js +25 -15
- package/node_modules/hono/dist/adapter/bun/websocket.js +61 -68
- package/node_modules/hono/dist/adapter/cloudflare-pages/conninfo.js +24 -9
- package/node_modules/hono/dist/adapter/cloudflare-pages/handler.js +59 -62
- package/node_modules/hono/dist/adapter/cloudflare-pages/index.js +2 -8
- package/node_modules/hono/dist/adapter/cloudflare-workers/conninfo.js +7 -9
- package/node_modules/hono/dist/adapter/cloudflare-workers/index.js +3 -8
- package/node_modules/hono/dist/adapter/cloudflare-workers/serve-static-module.js +5 -6
- package/node_modules/hono/dist/adapter/cloudflare-workers/serve-static.js +26 -20
- package/node_modules/hono/dist/adapter/cloudflare-workers/utils.js +21 -34
- package/node_modules/hono/dist/adapter/cloudflare-workers/websocket.js +31 -39
- package/node_modules/hono/dist/adapter/deno/conninfo.js +16 -13
- package/node_modules/hono/dist/adapter/deno/deno.d.js +1 -0
- package/node_modules/hono/dist/adapter/deno/index.js +3 -10
- package/node_modules/hono/dist/adapter/deno/serve-static.js +33 -38
- package/node_modules/hono/dist/adapter/deno/ssg.js +27 -16
- package/node_modules/hono/dist/adapter/deno/websocket.js +30 -30
- package/node_modules/hono/dist/adapter/lambda-edge/conninfo.js +7 -9
- package/node_modules/hono/dist/adapter/lambda-edge/handler.js +102 -101
- package/node_modules/hono/dist/adapter/lambda-edge/index.js +2 -6
- package/node_modules/hono/dist/adapter/netlify/conninfo.js +24 -9
- package/node_modules/hono/dist/adapter/netlify/handler.js +10 -8
- package/node_modules/hono/dist/adapter/netlify/index.js +3 -2
- package/node_modules/hono/dist/adapter/netlify/mod.js +2 -6
- package/node_modules/hono/dist/adapter/service-worker/handler.js +15 -19
- package/node_modules/hono/dist/adapter/service-worker/index.js +23 -7
- package/node_modules/hono/dist/adapter/service-worker/types.js +1 -0
- package/node_modules/hono/dist/adapter/vercel/conninfo.js +7 -10
- package/node_modules/hono/dist/adapter/vercel/handler.js +8 -6
- package/node_modules/hono/dist/adapter/vercel/index.js +2 -6
- package/node_modules/hono/dist/cjs/_virtual/_rolldown/runtime.js +33 -0
- package/node_modules/hono/dist/cjs/adapter/aws-lambda/conninfo.js +42 -44
- package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +326 -373
- package/node_modules/hono/dist/cjs/adapter/aws-lambda/index.js +7 -34
- package/node_modules/hono/dist/cjs/adapter/aws-lambda/types.js +0 -15
- package/node_modules/hono/dist/cjs/adapter/bun/conninfo.js +21 -47
- package/node_modules/hono/dist/cjs/adapter/bun/index.js +14 -45
- package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +29 -50
- package/node_modules/hono/dist/cjs/adapter/bun/server.js +11 -26
- package/node_modules/hono/dist/cjs/adapter/bun/ssg.js +24 -35
- package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +63 -91
- package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/conninfo.js +25 -31
- package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/handler.js +61 -85
- package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/index.js +7 -34
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/conninfo.js +8 -31
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/index.js +7 -33
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/serve-static-module.js +7 -29
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/serve-static.js +27 -42
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/utils.js +21 -55
- package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/websocket.js +33 -62
- package/node_modules/hono/dist/cjs/adapter/deno/conninfo.js +16 -34
- package/node_modules/hono/dist/cjs/adapter/deno/index.js +10 -38
- package/node_modules/hono/dist/cjs/adapter/deno/serve-static.js +33 -59
- package/node_modules/hono/dist/cjs/adapter/deno/ssg.js +27 -37
- package/node_modules/hono/dist/cjs/adapter/deno/websocket.js +32 -53
- package/node_modules/hono/dist/cjs/adapter/lambda-edge/conninfo.js +8 -31
- package/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +102 -130
- package/node_modules/hono/dist/cjs/adapter/lambda-edge/index.js +5 -30
- package/node_modules/hono/dist/cjs/adapter/netlify/conninfo.js +25 -31
- package/node_modules/hono/dist/cjs/adapter/netlify/handler.js +10 -29
- package/node_modules/hono/dist/cjs/adapter/netlify/index.js +5 -21
- package/node_modules/hono/dist/cjs/adapter/netlify/mod.js +5 -30
- package/node_modules/hono/dist/cjs/adapter/service-worker/handler.js +16 -41
- package/node_modules/hono/dist/cjs/adapter/service-worker/index.js +25 -30
- package/node_modules/hono/dist/cjs/adapter/service-worker/types.js +0 -15
- package/node_modules/hono/dist/cjs/adapter/vercel/conninfo.js +8 -32
- package/node_modules/hono/dist/cjs/adapter/vercel/handler.js +8 -27
- package/node_modules/hono/dist/cjs/adapter/vercel/index.js +5 -30
- package/node_modules/hono/dist/cjs/client/client.js +139 -212
- package/node_modules/hono/dist/cjs/client/fetch-result-please.js +62 -80
- package/node_modules/hono/dist/cjs/client/index.js +7 -32
- package/node_modules/hono/dist/cjs/client/types.js +0 -15
- package/node_modules/hono/dist/cjs/client/utils.js +54 -92
- package/node_modules/hono/dist/cjs/compose.js +49 -66
- package/node_modules/hono/dist/cjs/context.js +379 -450
- package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +47 -72
- package/node_modules/hono/dist/cjs/helper/accepts/index.js +3 -27
- package/node_modules/hono/dist/cjs/helper/adapter/index.js +33 -73
- package/node_modules/hono/dist/cjs/helper/conninfo/index.js +0 -15
- package/node_modules/hono/dist/cjs/helper/conninfo/types.js +0 -15
- package/node_modules/hono/dist/cjs/helper/cookie/index.js +75 -116
- package/node_modules/hono/dist/cjs/helper/css/common.js +165 -244
- package/node_modules/hono/dist/cjs/helper/css/index.js +136 -151
- package/node_modules/hono/dist/cjs/helper/dev/index.js +45 -71
- package/node_modules/hono/dist/cjs/helper/factory/index.js +30 -51
- package/node_modules/hono/dist/cjs/helper/html/index.js +32 -62
- package/node_modules/hono/dist/cjs/helper/proxy/index.js +113 -106
- package/node_modules/hono/dist/cjs/helper/route/index.js +123 -66
- package/node_modules/hono/dist/cjs/helper/ssg/index.js +19 -43
- package/node_modules/hono/dist/cjs/helper/ssg/middleware.js +56 -64
- package/node_modules/hono/dist/cjs/helper/ssg/plugins.js +55 -57
- package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +196 -296
- package/node_modules/hono/dist/cjs/helper/ssg/utils.js +47 -90
- package/node_modules/hono/dist/cjs/helper/streaming/index.js +8 -35
- package/node_modules/hono/dist/cjs/helper/streaming/sse.js +53 -85
- package/node_modules/hono/dist/cjs/helper/streaming/stream.js +23 -53
- package/node_modules/hono/dist/cjs/helper/streaming/text.js +10 -32
- package/node_modules/hono/dist/cjs/helper/streaming/utils.js +13 -32
- package/node_modules/hono/dist/cjs/helper/testing/index.js +16 -31
- package/node_modules/hono/dist/cjs/helper/websocket/index.js +51 -76
- package/node_modules/hono/dist/cjs/hono-base.js +345 -403
- package/node_modules/hono/dist/cjs/hono.js +28 -42
- package/node_modules/hono/dist/cjs/http-exception.js +55 -56
- package/node_modules/hono/dist/cjs/index.js +22 -30
- package/node_modules/hono/dist/cjs/jsx/base.js +237 -366
- package/node_modules/hono/dist/cjs/jsx/children.js +16 -41
- package/node_modules/hono/dist/cjs/jsx/components.js +119 -192
- package/node_modules/hono/dist/cjs/jsx/constants.js +15 -42
- package/node_modules/hono/dist/cjs/jsx/context.js +144 -162
- package/node_modules/hono/dist/cjs/jsx/dom/client.js +49 -69
- package/node_modules/hono/dist/cjs/jsx/dom/components.js +23 -52
- package/node_modules/hono/dist/cjs/jsx/dom/context.js +39 -67
- package/node_modules/hono/dist/cjs/jsx/dom/css.js +143 -158
- package/node_modules/hono/dist/cjs/jsx/dom/hooks/index.js +55 -64
- package/node_modules/hono/dist/cjs/jsx/dom/index.js +114 -173
- package/node_modules/hono/dist/cjs/jsx/dom/intrinsic-element/components.js +282 -375
- package/node_modules/hono/dist/cjs/jsx/dom/jsx-dev-runtime.js +14 -49
- package/node_modules/hono/dist/cjs/jsx/dom/jsx-runtime.js +5 -32
- package/node_modules/hono/dist/cjs/jsx/dom/render.js +469 -623
- package/node_modules/hono/dist/cjs/jsx/dom/server.js +37 -64
- package/node_modules/hono/dist/cjs/jsx/dom/utils.js +7 -30
- package/node_modules/hono/dist/cjs/jsx/hooks/index.js +225 -318
- package/node_modules/hono/dist/cjs/jsx/index.js +86 -135
- package/node_modules/hono/dist/cjs/jsx/intrinsic-element/common.js +20 -43
- package/node_modules/hono/dist/cjs/jsx/intrinsic-element/components.js +117 -168
- package/node_modules/hono/dist/cjs/jsx/intrinsic-elements.js +0 -15
- package/node_modules/hono/dist/cjs/jsx/jsx-dev-runtime.js +14 -39
- package/node_modules/hono/dist/cjs/jsx/jsx-runtime.js +34 -68
- package/node_modules/hono/dist/cjs/jsx/streaming.js +123 -166
- package/node_modules/hono/dist/cjs/jsx/types.js +0 -15
- package/node_modules/hono/dist/cjs/jsx/utils.js +91 -175
- package/node_modules/hono/dist/cjs/middleware/basic-auth/index.js +98 -86
- package/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +92 -109
- package/node_modules/hono/dist/cjs/middleware/body-limit/index.js +66 -72
- package/node_modules/hono/dist/cjs/middleware/cache/index.js +153 -199
- package/node_modules/hono/dist/cjs/middleware/combine/index.js +135 -95
- package/node_modules/hono/dist/cjs/middleware/compress/index.js +73 -88
- package/node_modules/hono/dist/cjs/middleware/context-storage/index.js +49 -41
- package/node_modules/hono/dist/cjs/middleware/cors/index.js +107 -107
- package/node_modules/hono/dist/cjs/middleware/csrf/index.js +101 -72
- package/node_modules/hono/dist/cjs/middleware/etag/digest.js +58 -97
- package/node_modules/hono/dist/cjs/middleware/etag/index.js +71 -91
- package/node_modules/hono/dist/cjs/middleware/ip-restriction/index.js +161 -169
- package/node_modules/hono/dist/cjs/middleware/jsx-renderer/index.js +99 -77
- package/node_modules/hono/dist/cjs/middleware/jwk/index.js +3 -27
- package/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +118 -135
- package/node_modules/hono/dist/cjs/middleware/jwt/index.js +9 -38
- package/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +120 -141
- package/node_modules/hono/dist/cjs/middleware/language/index.js +7 -35
- package/node_modules/hono/dist/cjs/middleware/language/language.js +184 -182
- package/node_modules/hono/dist/cjs/middleware/logger/index.js +41 -62
- package/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +82 -88
- package/node_modules/hono/dist/cjs/middleware/method-override/index.js +101 -102
- package/node_modules/hono/dist/cjs/middleware/powered-by/index.js +23 -30
- package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +38 -42
- package/node_modules/hono/dist/cjs/middleware/request-id/index.js +3 -27
- package/node_modules/hono/dist/cjs/middleware/request-id/request-id.js +34 -42
- package/node_modules/hono/dist/cjs/middleware/secure-headers/index.js +4 -29
- package/node_modules/hono/dist/cjs/middleware/secure-headers/permissions-policy.js +0 -15
- package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +142 -174
- package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +56 -93
- package/node_modules/hono/dist/cjs/middleware/serve-static/path.js +15 -38
- package/node_modules/hono/dist/cjs/middleware/timeout/index.js +40 -45
- package/node_modules/hono/dist/cjs/middleware/timing/index.js +7 -35
- package/node_modules/hono/dist/cjs/middleware/timing/timing.js +177 -118
- package/node_modules/hono/dist/cjs/middleware/trailing-slash/index.js +85 -58
- package/node_modules/hono/dist/cjs/preset/quick.js +18 -37
- package/node_modules/hono/dist/cjs/preset/tiny.js +15 -33
- package/node_modules/hono/dist/cjs/request/constants.js +5 -27
- package/node_modules/hono/dist/cjs/request.js +334 -346
- package/node_modules/hono/dist/cjs/router/linear-router/index.js +3 -27
- package/node_modules/hono/dist/cjs/router/linear-router/router.js +95 -143
- package/node_modules/hono/dist/cjs/router/pattern-router/index.js +3 -27
- package/node_modules/hono/dist/cjs/router/pattern-router/router.js +41 -63
- package/node_modules/hono/dist/cjs/router/reg-exp-router/index.js +7 -34
- package/node_modules/hono/dist/cjs/router/reg-exp-router/matcher.js +18 -45
- package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +91 -135
- package/node_modules/hono/dist/cjs/router/reg-exp-router/prepared-router.js +92 -161
- package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +98 -147
- package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +73 -89
- package/node_modules/hono/dist/cjs/router/smart-router/index.js +3 -27
- package/node_modules/hono/dist/cjs/router/smart-router/router.js +49 -79
- package/node_modules/hono/dist/cjs/router/trie-router/index.js +3 -27
- package/node_modules/hono/dist/cjs/router/trie-router/node.js +134 -186
- package/node_modules/hono/dist/cjs/router/trie-router/router.js +15 -39
- package/node_modules/hono/dist/cjs/router/utils.js +5 -27
- package/node_modules/hono/dist/cjs/router.js +37 -37
- package/node_modules/hono/dist/cjs/types.js +5 -28
- package/node_modules/hono/dist/cjs/utils/accept.js +177 -225
- package/node_modules/hono/dist/cjs/utils/basic-auth.js +16 -40
- package/node_modules/hono/dist/cjs/utils/body.js +84 -110
- package/node_modules/hono/dist/cjs/utils/buffer.js +43 -91
- package/node_modules/hono/dist/cjs/utils/color.js +35 -44
- package/node_modules/hono/dist/cjs/utils/compress.js +11 -26
- package/node_modules/hono/dist/cjs/utils/concurrent.js +29 -59
- package/node_modules/hono/dist/cjs/utils/constants.js +7 -26
- package/node_modules/hono/dist/cjs/utils/cookie.js +107 -177
- package/node_modules/hono/dist/cjs/utils/crypto.js +30 -61
- package/node_modules/hono/dist/cjs/utils/encode.js +31 -48
- package/node_modules/hono/dist/cjs/utils/filepath.js +23 -54
- package/node_modules/hono/dist/cjs/utils/handler.js +11 -33
- package/node_modules/hono/dist/cjs/utils/headers.js +0 -15
- package/node_modules/hono/dist/cjs/utils/html.js +96 -137
- package/node_modules/hono/dist/cjs/utils/http-status.js +0 -15
- package/node_modules/hono/dist/cjs/utils/ipaddr.js +213 -286
- package/node_modules/hono/dist/cjs/utils/jwt/index.js +14 -27
- package/node_modules/hono/dist/cjs/utils/jwt/jwa.js +25 -42
- package/node_modules/hono/dist/cjs/utils/jwt/jws.js +119 -199
- package/node_modules/hono/dist/cjs/utils/jwt/jwt.js +122 -206
- package/node_modules/hono/dist/cjs/utils/jwt/types.js +122 -159
- package/node_modules/hono/dist/cjs/utils/jwt/utf8.js +9 -28
- package/node_modules/hono/dist/cjs/utils/mime.js +75 -101
- package/node_modules/hono/dist/cjs/utils/stream.js +88 -111
- package/node_modules/hono/dist/cjs/utils/types.js +0 -15
- package/node_modules/hono/dist/cjs/utils/url.js +185 -234
- package/node_modules/hono/dist/cjs/validator/index.js +3 -27
- package/node_modules/hono/dist/cjs/validator/utils.js +0 -15
- package/node_modules/hono/dist/cjs/validator/validator.js +60 -103
- package/node_modules/hono/dist/client/client.js +138 -197
- package/node_modules/hono/dist/client/fetch-result-please.js +59 -56
- package/node_modules/hono/dist/client/index.js +3 -7
- package/node_modules/hono/dist/client/types.js +1 -0
- package/node_modules/hono/dist/client/utils.js +51 -68
- package/node_modules/hono/dist/compose.js +49 -45
- package/node_modules/hono/dist/context.js +376 -426
- package/node_modules/hono/dist/helper/accepts/accepts.js +47 -51
- package/node_modules/hono/dist/helper/accepts/index.js +1 -4
- package/node_modules/hono/dist/helper/adapter/index.js +33 -52
- package/node_modules/hono/dist/helper/conninfo/index.js +1 -0
- package/node_modules/hono/dist/helper/conninfo/types.js +1 -0
- package/node_modules/hono/dist/helper/cookie/index.js +74 -94
- package/node_modules/hono/dist/helper/css/common.js +167 -225
- package/node_modules/hono/dist/helper/css/index.js +132 -137
- package/node_modules/hono/dist/helper/dev/index.js +44 -49
- package/node_modules/hono/dist/helper/factory/index.js +27 -27
- package/node_modules/hono/dist/helper/html/index.js +30 -39
- package/node_modules/hono/dist/helper/proxy/index.js +116 -88
- package/node_modules/hono/dist/helper/route/index.js +121 -43
- package/node_modules/hono/dist/helper/ssg/index.js +3 -18
- package/node_modules/hono/dist/helper/ssg/middleware.js +53 -40
- package/node_modules/hono/dist/helper/ssg/plugins.js +55 -36
- package/node_modules/hono/dist/helper/ssg/ssg.js +198 -283
- package/node_modules/hono/dist/helper/ssg/utils.js +53 -75
- package/node_modules/hono/dist/helper/streaming/index.js +2 -8
- package/node_modules/hono/dist/helper/streaming/sse.js +50 -61
- package/node_modules/hono/dist/helper/streaming/stream.js +22 -31
- package/node_modules/hono/dist/helper/streaming/text.js +9 -10
- package/node_modules/hono/dist/helper/streaming/utils.js +9 -12
- package/node_modules/hono/dist/helper/testing/index.js +16 -10
- package/node_modules/hono/dist/helper/websocket/index.js +49 -53
- package/node_modules/hono/dist/hono-base.js +342 -379
- package/node_modules/hono/dist/hono.js +27 -20
- package/node_modules/hono/dist/http-exception.js +53 -33
- package/node_modules/hono/dist/index.js +19 -6
- package/node_modules/hono/dist/jsx/base.js +231 -340
- package/node_modules/hono/dist/jsx/children.js +16 -20
- package/node_modules/hono/dist/jsx/components.js +118 -170
- package/node_modules/hono/dist/jsx/constants.js +9 -15
- package/node_modules/hono/dist/jsx/context.js +153 -150
- package/node_modules/hono/dist/jsx/dom/client.js +45 -48
- package/node_modules/hono/dist/jsx/dom/components.js +21 -29
- package/node_modules/hono/dist/jsx/dom/context.js +37 -44
- package/node_modules/hono/dist/jsx/dom/css.js +142 -147
- package/node_modules/hono/dist/jsx/dom/hooks/index.js +52 -40
- package/node_modules/hono/dist/jsx/dom/index.js +71 -134
- package/node_modules/hono/dist/jsx/dom/intrinsic-element/components.js +275 -359
- package/node_modules/hono/dist/jsx/dom/jsx-dev-runtime.js +14 -18
- package/node_modules/hono/dist/jsx/dom/jsx-runtime.js +2 -8
- package/node_modules/hono/dist/jsx/dom/render.js +492 -631
- package/node_modules/hono/dist/jsx/dom/server.js +32 -32
- package/node_modules/hono/dist/jsx/dom/utils.js +6 -8
- package/node_modules/hono/dist/jsx/hooks/index.js +236 -308
- package/node_modules/hono/dist/jsx/index.js +45 -98
- package/node_modules/hono/dist/jsx/intrinsic-element/common.js +20 -22
- package/node_modules/hono/dist/jsx/intrinsic-element/components.js +113 -154
- package/node_modules/hono/dist/jsx/intrinsic-elements.js +1 -0
- package/node_modules/hono/dist/jsx/jsx-dev-runtime.js +12 -16
- package/node_modules/hono/dist/jsx/jsx-runtime.js +29 -42
- package/node_modules/hono/dist/jsx/streaming.js +120 -142
- package/node_modules/hono/dist/jsx/types.js +1 -0
- package/node_modules/hono/dist/jsx/utils.js +105 -168
- package/node_modules/hono/dist/middleware/basic-auth/index.js +96 -63
- package/node_modules/hono/dist/middleware/bearer-auth/index.js +93 -89
- package/node_modules/hono/dist/middleware/body-limit/index.js +66 -51
- package/node_modules/hono/dist/middleware/cache/index.js +165 -190
- package/node_modules/hono/dist/middleware/combine/index.js +134 -73
- package/node_modules/hono/dist/middleware/compress/index.js +75 -69
- package/node_modules/hono/dist/middleware/context-storage/index.js +49 -19
- package/node_modules/hono/dist/middleware/cors/index.js +107 -86
- package/node_modules/hono/dist/middleware/csrf/index.js +103 -53
- package/node_modules/hono/dist/middleware/etag/digest.js +59 -77
- package/node_modules/hono/dist/middleware/etag/index.js +71 -70
- package/node_modules/hono/dist/middleware/ip-restriction/index.js +163 -158
- package/node_modules/hono/dist/middleware/jsx-renderer/index.js +97 -54
- package/node_modules/hono/dist/middleware/jwk/index.js +1 -4
- package/node_modules/hono/dist/middleware/jwk/jwk.js +116 -112
- package/node_modules/hono/dist/middleware/jwt/index.js +2 -10
- package/node_modules/hono/dist/middleware/jwt/jwt.js +114 -114
- package/node_modules/hono/dist/middleware/language/index.js +2 -15
- package/node_modules/hono/dist/middleware/language/language.js +180 -157
- package/node_modules/hono/dist/middleware/logger/index.js +43 -37
- package/node_modules/hono/dist/middleware/method-not-allowed/index.js +81 -66
- package/node_modules/hono/dist/middleware/method-override/index.js +101 -81
- package/node_modules/hono/dist/middleware/powered-by/index.js +23 -9
- package/node_modules/hono/dist/middleware/pretty-json/index.js +39 -22
- package/node_modules/hono/dist/middleware/request-id/index.js +1 -4
- package/node_modules/hono/dist/middleware/request-id/request-id.js +33 -20
- package/node_modules/hono/dist/middleware/secure-headers/index.js +1 -5
- package/node_modules/hono/dist/middleware/secure-headers/permissions-policy.js +1 -0
- package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +144 -155
- package/node_modules/hono/dist/middleware/serve-static/index.js +56 -72
- package/node_modules/hono/dist/middleware/serve-static/path.js +15 -17
- package/node_modules/hono/dist/middleware/timeout/index.js +40 -23
- package/node_modules/hono/dist/middleware/timing/index.js +2 -9
- package/node_modules/hono/dist/middleware/timing/timing.js +177 -97
- package/node_modules/hono/dist/middleware/trailing-slash/index.js +85 -37
- package/node_modules/hono/dist/preset/quick.js +17 -15
- package/node_modules/hono/dist/preset/tiny.js +14 -11
- package/node_modules/hono/dist/request/constants.js +4 -5
- package/node_modules/hono/dist/request.js +328 -319
- package/node_modules/hono/dist/router/linear-router/index.js +1 -4
- package/node_modules/hono/dist/router/linear-router/router.js +93 -120
- package/node_modules/hono/dist/router/pattern-router/index.js +1 -4
- package/node_modules/hono/dist/router/pattern-router/router.js +39 -40
- package/node_modules/hono/dist/router/reg-exp-router/index.js +1 -7
- package/node_modules/hono/dist/router/reg-exp-router/matcher.js +17 -23
- package/node_modules/hono/dist/router/reg-exp-router/node.js +87 -110
- package/node_modules/hono/dist/router/reg-exp-router/prepared-router.js +89 -137
- package/node_modules/hono/dist/router/reg-exp-router/router.js +92 -129
- package/node_modules/hono/dist/router/reg-exp-router/trie.js +69 -64
- package/node_modules/hono/dist/router/smart-router/index.js +1 -4
- package/node_modules/hono/dist/router/smart-router/router.js +46 -55
- package/node_modules/hono/dist/router/trie-router/index.js +1 -4
- package/node_modules/hono/dist/router/trie-router/node.js +131 -162
- package/node_modules/hono/dist/router/trie-router/router.js +11 -14
- package/node_modules/hono/dist/router/utils.js +4 -5
- package/node_modules/hono/dist/router.js +35 -14
- package/node_modules/hono/dist/types/adapter/aws-lambda/conninfo.d.ts +4 -1
- package/node_modules/hono/dist/types/adapter/aws-lambda/handler.d.ts +150 -104
- package/node_modules/hono/dist/types/adapter/aws-lambda/index.d.ts +4 -8
- package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +152 -122
- package/node_modules/hono/dist/types/adapter/bun/conninfo.d.ts +4 -1
- package/node_modules/hono/dist/types/adapter/bun/index.d.ts +6 -10
- package/node_modules/hono/dist/types/adapter/bun/serve-static.d.ts +7 -2
- package/node_modules/hono/dist/types/adapter/bun/server.d.ts +4 -5
- package/node_modules/hono/dist/types/adapter/bun/ssg.d.ts +5 -1
- package/node_modules/hono/dist/types/adapter/bun/websocket.d.ts +31 -16
- package/node_modules/hono/dist/types/adapter/cloudflare-pages/conninfo.d.ts +4 -1
- package/node_modules/hono/dist/types/adapter/cloudflare-pages/handler.d.ts +29 -17
- package/node_modules/hono/dist/types/adapter/cloudflare-pages/index.d.ts +3 -7
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/conninfo.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/index.d.ts +4 -7
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/serve-static-module.d.ts +5 -2
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/serve-static.d.ts +10 -5
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/utils.d.ts +10 -2
- package/node_modules/hono/dist/types/adapter/cloudflare-workers/websocket.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/deno/conninfo.d.ts +4 -1
- package/node_modules/hono/dist/types/adapter/deno/deno.d.ts +1 -0
- package/node_modules/hono/dist/types/adapter/deno/index.d.ts +5 -8
- package/node_modules/hono/dist/types/adapter/deno/serve-static.d.ts +7 -2
- package/node_modules/hono/dist/types/adapter/deno/ssg.d.ts +5 -1
- package/node_modules/hono/dist/types/adapter/deno/websocket.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/lambda-edge/conninfo.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/lambda-edge/handler.d.ts +83 -57
- package/node_modules/hono/dist/types/adapter/lambda-edge/index.d.ts +3 -7
- package/node_modules/hono/dist/types/adapter/netlify/conninfo.d.ts +4 -1
- package/node_modules/hono/dist/types/adapter/netlify/handler.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/netlify/index.d.ts +3 -5
- package/node_modules/hono/dist/types/adapter/netlify/mod.d.ts +3 -2
- package/node_modules/hono/dist/types/adapter/service-worker/handler.d.ts +9 -7
- package/node_modules/hono/dist/types/adapter/service-worker/index.d.ts +7 -9
- package/node_modules/hono/dist/types/adapter/service-worker/types.d.ts +12 -7
- package/node_modules/hono/dist/types/adapter/vercel/conninfo.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/vercel/handler.d.ts +6 -1
- package/node_modules/hono/dist/types/adapter/vercel/index.d.ts +3 -6
- package/node_modules/hono/dist/types/client/client.d.ts +5 -3
- package/node_modules/hono/dist/types/client/fetch-result-please.d.ts +21 -19
- package/node_modules/hono/dist/types/client/index.d.ts +5 -7
- package/node_modules/hono/dist/types/client/types.d.ts +134 -159
- package/node_modules/hono/dist/types/client/utils.d.ts +6 -4
- package/node_modules/hono/dist/types/compose.d.ts +4 -2
- package/node_modules/hono/dist/types/context.d.ts +335 -335
- package/node_modules/hono/dist/types/helper/accepts/accepts.d.ts +11 -9
- package/node_modules/hono/dist/types/helper/accepts/index.d.ts +2 -5
- package/node_modules/hono/dist/types/helper/adapter/index.d.ts +4 -6
- package/node_modules/hono/dist/types/helper/conninfo/index.d.ts +2 -5
- package/node_modules/hono/dist/types/helper/conninfo/types.d.ts +25 -23
- package/node_modules/hono/dist/types/helper/cookie/index.d.ts +10 -12
- package/node_modules/hono/dist/types/helper/css/common.d.ts +11 -9
- package/node_modules/hono/dist/types/helper/css/index.d.ts +26 -28
- package/node_modules/hono/dist/types/helper/dev/index.d.ts +10 -12
- package/node_modules/hono/dist/types/helper/factory/index.d.ts +26 -73
- package/node_modules/hono/dist/types/helper/html/index.d.ts +4 -7
- package/node_modules/hono/dist/types/helper/proxy/index.d.ts +19 -21
- package/node_modules/hono/dist/types/helper/route/index.d.ts +4 -2
- package/node_modules/hono/dist/types/helper/ssg/index.d.ts +4 -7
- package/node_modules/hono/dist/types/helper/ssg/middleware.d.ts +8 -6
- package/node_modules/hono/dist/types/helper/ssg/plugins.d.ts +3 -1
- package/node_modules/hono/dist/types/helper/ssg/ssg.d.ts +38 -36
- package/node_modules/hono/dist/types/helper/ssg/utils.d.ts +5 -3
- package/node_modules/hono/dist/types/helper/streaming/index.d.ts +4 -8
- package/node_modules/hono/dist/types/helper/streaming/sse.d.ts +10 -8
- package/node_modules/hono/dist/types/helper/streaming/stream.d.ts +4 -2
- package/node_modules/hono/dist/types/helper/streaming/text.d.ts +4 -2
- package/node_modules/hono/dist/types/helper/streaming/utils.d.ts +2 -0
- package/node_modules/hono/dist/types/helper/testing/index.d.ts +7 -9
- package/node_modules/hono/dist/types/helper/websocket/index.d.ts +30 -33
- package/node_modules/hono/dist/types/hono-base.d.ts +208 -210
- package/node_modules/hono/dist/types/hono.d.ts +11 -10
- package/node_modules/hono/dist/types/http-exception.d.ts +20 -22
- package/node_modules/hono/dist/types/index.d.ts +6 -37
- package/node_modules/hono/dist/types/jsx/base.d.ts +36 -34
- package/node_modules/hono/dist/types/jsx/children.d.ts +8 -6
- package/node_modules/hono/dist/types/jsx/components.d.ts +8 -5
- package/node_modules/hono/dist/types/jsx/constants.d.ts +2 -0
- package/node_modules/hono/dist/types/jsx/context.d.ts +9 -6
- package/node_modules/hono/dist/types/jsx/dom/client.d.ts +9 -10
- package/node_modules/hono/dist/types/jsx/dom/components.d.ts +9 -6
- package/node_modules/hono/dist/types/jsx/dom/context.d.ts +3 -1
- package/node_modules/hono/dist/types/jsx/dom/css.d.ts +27 -30
- package/node_modules/hono/dist/types/jsx/dom/hooks/index.d.ts +11 -12
- package/node_modules/hono/dist/types/jsx/dom/index.d.ts +79 -83
- package/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +9 -5
- package/node_modules/hono/dist/types/jsx/dom/jsx-dev-runtime.d.ts +4 -6
- package/node_modules/hono/dist/types/jsx/dom/jsx-runtime.d.ts +3 -7
- package/node_modules/hono/dist/types/jsx/dom/render.d.ts +32 -50
- package/node_modules/hono/dist/types/jsx/dom/server.d.ts +87 -85
- package/node_modules/hono/dist/types/jsx/dom/utils.d.ts +2 -0
- package/node_modules/hono/dist/types/jsx/hooks/index.d.ts +16 -16
- package/node_modules/hono/dist/types/jsx/index.d.ts +71 -73
- package/node_modules/hono/dist/types/jsx/intrinsic-element/common.d.ts +3 -1
- package/node_modules/hono/dist/types/jsx/intrinsic-element/components.d.ts +7 -4
- package/node_modules/hono/dist/types/jsx/intrinsic-elements.d.ts +708 -708
- package/node_modules/hono/dist/types/jsx/jsx-dev-runtime.d.ts +4 -7
- package/node_modules/hono/dist/types/jsx/jsx-runtime.d.ts +7 -10
- package/node_modules/hono/dist/types/jsx/streaming.d.ts +9 -10
- package/node_modules/hono/dist/types/jsx/types.d.ts +12 -13
- package/node_modules/hono/dist/types/jsx/utils.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/basic-auth/index.d.ts +17 -19
- package/node_modules/hono/dist/types/middleware/bearer-auth/index.d.ts +46 -48
- package/node_modules/hono/dist/types/middleware/body-limit/index.d.ts +6 -8
- package/node_modules/hono/dist/types/middleware/cache/index.d.ts +13 -15
- package/node_modules/hono/dist/types/middleware/combine/index.d.ts +4 -6
- package/node_modules/hono/dist/types/middleware/compress/index.d.ts +9 -10
- package/node_modules/hono/dist/types/middleware/context-storage/index.d.ts +4 -6
- package/node_modules/hono/dist/types/middleware/cors/index.d.ts +10 -12
- package/node_modules/hono/dist/types/middleware/csrf/index.d.ts +6 -8
- package/node_modules/hono/dist/types/middleware/etag/digest.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/etag/index.d.ts +6 -8
- package/node_modules/hono/dist/types/middleware/ip-restriction/index.d.ts +11 -12
- package/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +11 -11
- package/node_modules/hono/dist/types/middleware/jwk/index.d.ts +2 -1
- package/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +20 -23
- package/node_modules/hono/dist/types/middleware/jwt/index.d.ts +7 -6
- package/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +28 -30
- package/node_modules/hono/dist/types/middleware/language/index.d.ts +6 -5
- package/node_modules/hono/dist/types/middleware/language/language.d.ts +42 -44
- package/node_modules/hono/dist/types/middleware/logger/index.d.ts +3 -5
- package/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +7 -9
- package/node_modules/hono/dist/types/middleware/method-override/index.d.ts +14 -16
- package/node_modules/hono/dist/types/middleware/powered-by/index.d.ts +8 -10
- package/node_modules/hono/dist/types/middleware/pretty-json/index.d.ts +18 -20
- package/node_modules/hono/dist/types/middleware/request-id/index.d.ts +6 -5
- package/node_modules/hono/dist/types/middleware/request-id/request-id.d.ts +9 -11
- package/node_modules/hono/dist/types/middleware/secure-headers/index.d.ts +6 -6
- package/node_modules/hono/dist/types/middleware/secure-headers/permissions-policy.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/secure-headers/secure-headers.d.ts +55 -57
- package/node_modules/hono/dist/types/middleware/serve-static/index.d.ts +24 -24
- package/node_modules/hono/dist/types/middleware/serve-static/path.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/timeout/index.d.ts +5 -7
- package/node_modules/hono/dist/types/middleware/timing/index.d.ts +6 -5
- package/node_modules/hono/dist/types/middleware/timing/timing.d.ts +17 -20
- package/node_modules/hono/dist/types/middleware/trailing-slash/index.d.ts +35 -37
- package/node_modules/hono/dist/types/preset/quick.d.ts +6 -9
- package/node_modules/hono/dist/types/preset/tiny.d.ts +6 -9
- package/node_modules/hono/dist/types/request/constants.d.ts +2 -0
- package/node_modules/hono/dist/types/request.d.ts +288 -286
- package/node_modules/hono/dist/types/router/linear-router/index.d.ts +2 -5
- package/node_modules/hono/dist/types/router/linear-router/router.d.ts +7 -5
- package/node_modules/hono/dist/types/router/pattern-router/index.d.ts +2 -5
- package/node_modules/hono/dist/types/router/pattern-router/router.d.ts +7 -5
- package/node_modules/hono/dist/types/router/reg-exp-router/index.d.ts +3 -6
- package/node_modules/hono/dist/types/router/reg-exp-router/matcher.d.ts +3 -1
- package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +6 -4
- package/node_modules/hono/dist/types/router/reg-exp-router/prepared-router.d.ts +11 -10
- package/node_modules/hono/dist/types/router/reg-exp-router/router.d.ts +10 -9
- package/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +7 -5
- package/node_modules/hono/dist/types/router/smart-router/index.d.ts +2 -5
- package/node_modules/hono/dist/types/router/smart-router/router.d.ts +11 -9
- package/node_modules/hono/dist/types/router/trie-router/index.d.ts +2 -5
- package/node_modules/hono/dist/types/router/trie-router/node.d.ts +6 -4
- package/node_modules/hono/dist/types/router/trie-router/router.d.ts +7 -5
- package/node_modules/hono/dist/types/router/utils.d.ts +2 -0
- package/node_modules/hono/dist/types/router.d.ts +23 -22
- package/node_modules/hono/dist/types/types.d.ts +146 -505
- package/node_modules/hono/dist/types/utils/accept.d.ts +5 -3
- package/node_modules/hono/dist/types/utils/basic-auth.d.ts +4 -2
- package/node_modules/hono/dist/types/utils/body.d.ts +46 -50
- package/node_modules/hono/dist/types/utils/buffer.d.ts +7 -5
- package/node_modules/hono/dist/types/utils/color.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/compress.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/concurrent.d.ts +6 -4
- package/node_modules/hono/dist/types/utils/constants.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/cookie.d.ts +20 -18
- package/node_modules/hono/dist/types/utils/crypto.d.ts +5 -7
- package/node_modules/hono/dist/types/utils/encode.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/filepath.d.ts +5 -3
- package/node_modules/hono/dist/types/utils/handler.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/headers.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/html.d.ts +11 -9
- package/node_modules/hono/dist/types/utils/http-status.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/ipaddr.d.ts +4 -6
- package/node_modules/hono/dist/types/utils/jwt/index.d.ts +18 -12
- package/node_modules/hono/dist/types/utils/jwt/jwa.d.ts +15 -13
- package/node_modules/hono/dist/types/utils/jwt/jws.d.ts +4 -7
- package/node_modules/hono/dist/types/utils/jwt/jwt.d.ts +26 -29
- package/node_modules/hono/dist/types/utils/jwt/types.d.ts +48 -45
- package/node_modules/hono/dist/types/utils/jwt/utf8.d.ts +2 -0
- package/node_modules/hono/dist/types/utils/mime.d.ts +60 -57
- package/node_modules/hono/dist/types/utils/stream.d.ts +27 -25
- package/node_modules/hono/dist/types/utils/types.d.ts +14 -26
- package/node_modules/hono/dist/types/utils/url.d.ts +2 -0
- package/node_modules/hono/dist/types/validator/index.d.ts +3 -7
- package/node_modules/hono/dist/types/validator/utils.d.ts +6 -8
- package/node_modules/hono/dist/types/validator/validator.d.ts +11 -9
- package/node_modules/hono/dist/types.js +4 -6
- package/node_modules/hono/dist/utils/accept.js +185 -212
- package/node_modules/hono/dist/utils/basic-auth.js +18 -21
- package/node_modules/hono/dist/utils/body.js +87 -92
- package/node_modules/hono/dist/utils/buffer.js +44 -71
- package/node_modules/hono/dist/utils/color.js +33 -21
- package/node_modules/hono/dist/utils/compress.js +11 -5
- package/node_modules/hono/dist/utils/concurrent.js +29 -38
- package/node_modules/hono/dist/utils/constants.js +7 -5
- package/node_modules/hono/dist/utils/cookie.js +114 -163
- package/node_modules/hono/dist/utils/crypto.js +30 -40
- package/node_modules/hono/dist/utils/encode.js +30 -26
- package/node_modules/hono/dist/utils/filepath.js +23 -33
- package/node_modules/hono/dist/utils/handler.js +10 -11
- package/node_modules/hono/dist/utils/headers.js +1 -0
- package/node_modules/hono/dist/utils/html.js +97 -117
- package/node_modules/hono/dist/utils/http-status.js +1 -0
- package/node_modules/hono/dist/utils/ipaddr.js +227 -279
- package/node_modules/hono/dist/utils/jwt/index.js +12 -4
- package/node_modules/hono/dist/utils/jwt/jwa.js +24 -20
- package/node_modules/hono/dist/utils/jwt/jws.js +115 -174
- package/node_modules/hono/dist/utils/jwt/jwt.js +120 -198
- package/node_modules/hono/dist/utils/jwt/types.js +79 -95
- package/node_modules/hono/dist/utils/jwt/utf8.js +9 -7
- package/node_modules/hono/dist/utils/mime.js +74 -79
- package/node_modules/hono/dist/utils/stream.js +86 -88
- package/node_modules/hono/dist/utils/types.js +1 -0
- package/node_modules/hono/dist/utils/url.js +187 -215
- package/node_modules/hono/dist/validator/index.js +1 -4
- package/node_modules/hono/dist/validator/utils.js +1 -0
- package/node_modules/hono/dist/validator/validator.js +61 -83
- package/node_modules/hono/package.json +27 -27
- package/node_modules/undici/LICENSE +21 -0
- package/node_modules/undici/README.md +741 -0
- package/node_modules/undici/docs/docs/api/Agent.md +84 -0
- package/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
- package/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
- package/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
- package/node_modules/undici/docs/docs/api/Client.md +288 -0
- package/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
- package/node_modules/undici/docs/docs/api/Connector.md +115 -0
- package/node_modules/undici/docs/docs/api/ContentType.md +57 -0
- package/node_modules/undici/docs/docs/api/Cookies.md +128 -0
- package/node_modules/undici/docs/docs/api/Debug.md +62 -0
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +317 -0
- package/node_modules/undici/docs/docs/api/Dispatcher.md +1393 -0
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
- package/node_modules/undici/docs/docs/api/Errors.md +49 -0
- package/node_modules/undici/docs/docs/api/EventSource.md +45 -0
- package/node_modules/undici/docs/docs/api/Fetch.md +60 -0
- package/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
- package/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
- package/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
- package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
- package/node_modules/undici/docs/docs/api/MockClient.md +81 -0
- package/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
- package/node_modules/undici/docs/docs/api/MockPool.md +555 -0
- package/node_modules/undici/docs/docs/api/Pool.md +84 -0
- package/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
- package/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
- package/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +275 -0
- package/node_modules/undici/docs/docs/api/Util.md +25 -0
- package/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
- package/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
- package/node_modules/undici/docs/docs/best-practices/crawling.md +58 -0
- package/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
- package/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
- package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +224 -0
- package/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
- package/node_modules/undici/index-fetch.js +65 -0
- package/node_modules/undici/index.d.ts +3 -0
- package/node_modules/undici/index.js +234 -0
- package/node_modules/undici/lib/api/abort-signal.js +59 -0
- package/node_modules/undici/lib/api/api-connect.js +110 -0
- package/node_modules/undici/lib/api/api-pipeline.js +252 -0
- package/node_modules/undici/lib/api/api-request.js +214 -0
- package/node_modules/undici/lib/api/api-stream.js +209 -0
- package/node_modules/undici/lib/api/api-upgrade.js +111 -0
- package/node_modules/undici/lib/api/index.js +7 -0
- package/node_modules/undici/lib/api/readable.js +580 -0
- package/node_modules/undici/lib/cache/memory-cache-store.js +279 -0
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +467 -0
- package/node_modules/undici/lib/core/connect.js +153 -0
- package/node_modules/undici/lib/core/constants.js +143 -0
- package/node_modules/undici/lib/core/diagnostics.js +227 -0
- package/node_modules/undici/lib/core/errors.js +477 -0
- package/node_modules/undici/lib/core/request.js +485 -0
- package/node_modules/undici/lib/core/socks5-client.js +422 -0
- package/node_modules/undici/lib/core/socks5-utils.js +212 -0
- package/node_modules/undici/lib/core/symbols.js +75 -0
- package/node_modules/undici/lib/core/tree.js +160 -0
- package/node_modules/undici/lib/core/util.js +992 -0
- package/node_modules/undici/lib/dispatcher/agent.js +158 -0
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +221 -0
- package/node_modules/undici/lib/dispatcher/client-h1.js +1746 -0
- package/node_modules/undici/lib/dispatcher/client-h2.js +1060 -0
- package/node_modules/undici/lib/dispatcher/client.js +668 -0
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +184 -0
- package/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
- package/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
- package/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
- package/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
- package/node_modules/undici/lib/dispatcher/pool.js +118 -0
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +319 -0
- package/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +260 -0
- package/node_modules/undici/lib/encoding/index.js +33 -0
- package/node_modules/undici/lib/global.js +59 -0
- package/node_modules/undici/lib/handler/cache-handler.js +776 -0
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
- package/node_modules/undici/lib/handler/decorator-handler.js +67 -0
- package/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
- package/node_modules/undici/lib/handler/redirect-handler.js +238 -0
- package/node_modules/undici/lib/handler/retry-handler.js +504 -0
- package/node_modules/undici/lib/handler/unwrap-handler.js +106 -0
- package/node_modules/undici/lib/handler/wrap-handler.js +105 -0
- package/node_modules/undici/lib/interceptor/cache.js +621 -0
- package/node_modules/undici/lib/interceptor/decompress.js +551 -0
- package/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
- package/node_modules/undici/lib/interceptor/dns.js +571 -0
- package/node_modules/undici/lib/interceptor/dump.js +99 -0
- package/node_modules/undici/lib/interceptor/redirect.js +21 -0
- package/node_modules/undici/lib/interceptor/response-error.js +95 -0
- package/node_modules/undici/lib/interceptor/retry.js +19 -0
- package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/node_modules/undici/lib/llhttp/constants.d.ts +195 -0
- package/node_modules/undici/lib/llhttp/constants.js +531 -0
- package/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
- package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
- package/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
- package/node_modules/undici/lib/llhttp/utils.js +12 -0
- package/node_modules/undici/lib/mock/mock-agent.js +232 -0
- package/node_modules/undici/lib/mock/mock-call-history.js +248 -0
- package/node_modules/undici/lib/mock/mock-client.js +68 -0
- package/node_modules/undici/lib/mock/mock-errors.js +29 -0
- package/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
- package/node_modules/undici/lib/mock/mock-pool.js +68 -0
- package/node_modules/undici/lib/mock/mock-symbols.js +32 -0
- package/node_modules/undici/lib/mock/mock-utils.js +486 -0
- package/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
- package/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
- package/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
- package/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
- package/node_modules/undici/lib/util/cache.js +676 -0
- package/node_modules/undici/lib/util/date.js +670 -0
- package/node_modules/undici/lib/util/promise.js +28 -0
- package/node_modules/undici/lib/util/runtime-features.js +124 -0
- package/node_modules/undici/lib/util/stats.js +32 -0
- package/node_modules/undici/lib/util/timers.js +425 -0
- package/node_modules/undici/lib/web/cache/cache.js +864 -0
- package/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
- package/node_modules/undici/lib/web/cache/util.js +45 -0
- package/node_modules/undici/lib/web/cookies/constants.js +12 -0
- package/node_modules/undici/lib/web/cookies/index.js +199 -0
- package/node_modules/undici/lib/web/cookies/parse.js +314 -0
- package/node_modules/undici/lib/web/cookies/util.js +352 -0
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +494 -0
- package/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
- package/node_modules/undici/lib/web/eventsource/util.js +29 -0
- package/node_modules/undici/lib/web/fetch/LICENSE +21 -0
- package/node_modules/undici/lib/web/fetch/body.js +509 -0
- package/node_modules/undici/lib/web/fetch/constants.js +131 -0
- package/node_modules/undici/lib/web/fetch/data-url.js +596 -0
- package/node_modules/undici/lib/web/fetch/formdata-parser.js +586 -0
- package/node_modules/undici/lib/web/fetch/formdata.js +259 -0
- package/node_modules/undici/lib/web/fetch/global.js +40 -0
- package/node_modules/undici/lib/web/fetch/headers.js +719 -0
- package/node_modules/undici/lib/web/fetch/index.js +2413 -0
- package/node_modules/undici/lib/web/fetch/request.js +1115 -0
- package/node_modules/undici/lib/web/fetch/response.js +641 -0
- package/node_modules/undici/lib/web/fetch/util.js +1522 -0
- package/node_modules/undici/lib/web/infra/index.js +229 -0
- package/node_modules/undici/lib/web/subresource-integrity/Readme.md +9 -0
- package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
- package/node_modules/undici/lib/web/webidl/index.js +1006 -0
- package/node_modules/undici/lib/web/websocket/connection.js +339 -0
- package/node_modules/undici/lib/web/websocket/constants.js +126 -0
- package/node_modules/undici/lib/web/websocket/events.js +331 -0
- package/node_modules/undici/lib/web/websocket/frame.js +133 -0
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +105 -0
- package/node_modules/undici/lib/web/websocket/receiver.js +507 -0
- package/node_modules/undici/lib/web/websocket/sender.js +109 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +496 -0
- package/node_modules/undici/lib/web/websocket/util.js +347 -0
- package/node_modules/undici/lib/web/websocket/websocket.js +758 -0
- package/node_modules/undici/package.json +152 -0
- package/node_modules/undici/scripts/strip-comments.js +10 -0
- package/node_modules/undici/types/README.md +6 -0
- package/node_modules/undici/types/agent.d.ts +32 -0
- package/node_modules/undici/types/api.d.ts +43 -0
- package/node_modules/undici/types/balanced-pool.d.ts +30 -0
- package/node_modules/undici/types/cache-interceptor.d.ts +179 -0
- package/node_modules/undici/types/cache.d.ts +36 -0
- package/node_modules/undici/types/client-stats.d.ts +15 -0
- package/node_modules/undici/types/client.d.ts +139 -0
- package/node_modules/undici/types/connector.d.ts +36 -0
- package/node_modules/undici/types/content-type.d.ts +21 -0
- package/node_modules/undici/types/cookies.d.ts +30 -0
- package/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
- package/node_modules/undici/types/dispatcher.d.ts +275 -0
- package/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
- package/node_modules/undici/types/errors.d.ts +177 -0
- package/node_modules/undici/types/eventsource.d.ts +66 -0
- package/node_modules/undici/types/fetch.d.ts +231 -0
- package/node_modules/undici/types/formdata.d.ts +114 -0
- package/node_modules/undici/types/global-dispatcher.d.ts +9 -0
- package/node_modules/undici/types/global-origin.d.ts +7 -0
- package/node_modules/undici/types/h2c-client.d.ts +73 -0
- package/node_modules/undici/types/handlers.d.ts +14 -0
- package/node_modules/undici/types/header.d.ts +160 -0
- package/node_modules/undici/types/index.d.ts +91 -0
- package/node_modules/undici/types/interceptors.d.ts +82 -0
- package/node_modules/undici/types/mock-agent.d.ts +68 -0
- package/node_modules/undici/types/mock-call-history.d.ts +111 -0
- package/node_modules/undici/types/mock-client.d.ts +27 -0
- package/node_modules/undici/types/mock-errors.d.ts +12 -0
- package/node_modules/undici/types/mock-interceptor.d.ts +94 -0
- package/node_modules/undici/types/mock-pool.d.ts +27 -0
- package/node_modules/undici/types/patch.d.ts +29 -0
- package/node_modules/undici/types/pool-stats.d.ts +19 -0
- package/node_modules/undici/types/pool.d.ts +41 -0
- package/node_modules/undici/types/proxy-agent.d.ts +29 -0
- package/node_modules/undici/types/readable.d.ts +68 -0
- package/node_modules/undici/types/retry-agent.d.ts +8 -0
- package/node_modules/undici/types/retry-handler.d.ts +125 -0
- package/node_modules/undici/types/round-robin-pool.d.ts +41 -0
- package/node_modules/undici/types/snapshot-agent.d.ts +109 -0
- package/node_modules/undici/types/socks5-proxy-agent.d.ts +25 -0
- package/node_modules/undici/types/util.d.ts +18 -0
- package/node_modules/undici/types/utility.d.ts +7 -0
- package/node_modules/undici/types/webidl.d.ts +347 -0
- package/node_modules/undici/types/websocket.d.ts +188 -0
- package/package.json +5 -3
- package/profiles/README.md +20 -0
- package/profiles/index.json +2 -1
- package/profiles/sales/0.1.profile.json +252 -0
- package/server.js +99 -0
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "./chunk-3BNWN6VP.mjs";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
-
import { randomBytes as
|
|
8
|
-
import { existsSync as
|
|
9
|
-
import { dirname as
|
|
7
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
8
|
+
import { existsSync as existsSync9, readFileSync as readFileSync11, renameSync as renameSync2 } from "fs";
|
|
9
|
+
import { dirname as dirname8, join as join11 } from "path";
|
|
10
10
|
import { homedir as homedir7 } from "os";
|
|
11
11
|
import express from "express";
|
|
12
12
|
import { createProxyMiddleware } from "http-proxy-middleware";
|
|
@@ -110,6 +110,31 @@ var Vault = class {
|
|
|
110
110
|
this.clearKey();
|
|
111
111
|
this.lockedReason = "expired";
|
|
112
112
|
}
|
|
113
|
+
/** Lock because the live Authority Server key no longer matches the one
|
|
114
|
+
* pinned at pairing — see as-pairing.ts / gatekeeper.ts. Mirrors
|
|
115
|
+
* lockExpired() exactly; the only difference callers care about is WHY. */
|
|
116
|
+
lockAsKeyMismatch() {
|
|
117
|
+
this.clearKey();
|
|
118
|
+
this.lockedReason = "as-key-mismatch";
|
|
119
|
+
}
|
|
120
|
+
/** Lock because a pin-tls-enforced connection to the Authority Server
|
|
121
|
+
* presented a certificate whose public key doesn't match the one pinned
|
|
122
|
+
* at pairing — see as-tls-pin.ts. Mirrors lockAsKeyMismatch() exactly. */
|
|
123
|
+
lockAsTlsMismatch() {
|
|
124
|
+
this.clearKey();
|
|
125
|
+
this.lockedReason = "as-tls-mismatch";
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Boot-time only: record that the gateway starts locked because the
|
|
129
|
+
* resolved Authority Server URL differs from the one it was last paired
|
|
130
|
+
* with. Deliberately does NOT call clearKey() — the vault always boots
|
|
131
|
+
* locked already (nothing has been unlocked yet in this process), so there
|
|
132
|
+
* is no session to end; this only attaches the reason so /health and the
|
|
133
|
+
* locked-agent notice can explain it instead of defaulting to "restart".
|
|
134
|
+
*/
|
|
135
|
+
markBootLockedAsUrlChanged() {
|
|
136
|
+
this.lockedReason = "as-url-changed";
|
|
137
|
+
}
|
|
113
138
|
/** What locked the vault, if known. `null` covers both "still unlocked"
|
|
114
139
|
* and the default boot-locked case — callers that care about the
|
|
115
140
|
* difference should check `isUnlocked()` first. */
|
|
@@ -300,10 +325,11 @@ async function configure(sessionCookie, vaultKeyHex) {
|
|
|
300
325
|
clearTimeout(timeout);
|
|
301
326
|
}
|
|
302
327
|
}
|
|
303
|
-
async function unconfigureSession() {
|
|
328
|
+
async function unconfigureSession(reason) {
|
|
304
329
|
const res = await fetch(`${MCP_BASE}/internal/clear-session`, {
|
|
305
330
|
method: "POST",
|
|
306
|
-
headers: internalHeaders()
|
|
331
|
+
headers: internalHeaders(),
|
|
332
|
+
body: JSON.stringify({ reason })
|
|
307
333
|
});
|
|
308
334
|
if (!res.ok) {
|
|
309
335
|
throw new Error(`MCP clear-session failed: ${res.status}`);
|
|
@@ -465,6 +491,13 @@ async function getEnrichedAuthorizations() {
|
|
|
465
491
|
if (!res.ok) throw new Error("Failed to fetch authorizations");
|
|
466
492
|
return res.json();
|
|
467
493
|
}
|
|
494
|
+
async function getSkippedCommitments() {
|
|
495
|
+
const res = await fetch(`${MCP_BASE}/internal/skipped-commitments`, {
|
|
496
|
+
headers: internalHeaders()
|
|
497
|
+
});
|
|
498
|
+
if (!res.ok) throw new Error("Failed to fetch skipped commitments");
|
|
499
|
+
return res.json();
|
|
500
|
+
}
|
|
468
501
|
async function getLocalEvidence() {
|
|
469
502
|
const res = await fetch(`${MCP_BASE}/internal/evidence`, {
|
|
470
503
|
headers: internalHeaders()
|
|
@@ -634,10 +667,510 @@ function clientVersionHeaders() {
|
|
|
634
667
|
};
|
|
635
668
|
}
|
|
636
669
|
|
|
670
|
+
// src/lib/as-pairing.ts
|
|
671
|
+
import { createHash as createHash2 } from "crypto";
|
|
672
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
673
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
674
|
+
function pairingPath(dataDir) {
|
|
675
|
+
return join3(dataDir, "as-pairing.json");
|
|
676
|
+
}
|
|
677
|
+
function readPairing(dataDir) {
|
|
678
|
+
const path = pairingPath(dataDir);
|
|
679
|
+
if (!existsSync2(path)) return null;
|
|
680
|
+
try {
|
|
681
|
+
const data = JSON.parse(readFileSync3(path, "utf-8"));
|
|
682
|
+
if (typeof data.asUrl !== "string" || typeof data.publicKeyHex !== "string") return null;
|
|
683
|
+
return {
|
|
684
|
+
asUrl: data.asUrl,
|
|
685
|
+
publicKeyHex: data.publicKeyHex,
|
|
686
|
+
pairedAt: data.pairedAt ?? "",
|
|
687
|
+
...typeof data.tlsSpkiPinHex === "string" ? { tlsSpkiPinHex: data.tlsSpkiPinHex } : {}
|
|
688
|
+
};
|
|
689
|
+
} catch {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function writePairing(dataDir, asUrl, publicKeyHex, opts = {}) {
|
|
694
|
+
const pairing = {
|
|
695
|
+
asUrl,
|
|
696
|
+
publicKeyHex,
|
|
697
|
+
pairedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
698
|
+
...opts.tlsSpkiPinHex ? { tlsSpkiPinHex: opts.tlsSpkiPinHex } : {}
|
|
699
|
+
};
|
|
700
|
+
const path = pairingPath(dataDir);
|
|
701
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
702
|
+
writeFileSync2(path, JSON.stringify(pairing, null, 2), { encoding: "utf-8", mode: 384 });
|
|
703
|
+
return pairing;
|
|
704
|
+
}
|
|
705
|
+
function recordTlsPin(dataDir, asUrl, tlsSpkiPinHex) {
|
|
706
|
+
const existing = readPairing(dataDir);
|
|
707
|
+
if (!existing || existing.asUrl !== asUrl) return;
|
|
708
|
+
const path = pairingPath(dataDir);
|
|
709
|
+
writeFileSync2(
|
|
710
|
+
path,
|
|
711
|
+
JSON.stringify({ ...existing, tlsSpkiPinHex }, null, 2),
|
|
712
|
+
{ encoding: "utf-8", mode: 384 }
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
function clearPairing(dataDir) {
|
|
716
|
+
const path = pairingPath(dataDir);
|
|
717
|
+
try {
|
|
718
|
+
if (existsSync2(path)) unlinkSync(path);
|
|
719
|
+
} catch {
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function fingerprintOf(publicKeyHex) {
|
|
723
|
+
const raw = Buffer.from(publicKeyHex, "hex");
|
|
724
|
+
const digest = createHash2("sha256").update(raw).digest("hex").toUpperCase();
|
|
725
|
+
return digest.match(/.{1,4}/g)?.join(":") ?? digest;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// src/lib/as-challenge.ts
|
|
729
|
+
import { createPublicKey, randomBytes as randomBytes2, verify as cryptoVerify } from "crypto";
|
|
730
|
+
import { canonicalize } from "@hap/core";
|
|
731
|
+
|
|
732
|
+
// src/lib/as-tls-pin.ts
|
|
733
|
+
import { createHash as createHash3 } from "crypto";
|
|
734
|
+
import { checkServerIdentity as defaultCheckServerIdentity, rootCertificates } from "tls";
|
|
735
|
+
import { Agent as HttpsAgent } from "https";
|
|
736
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
737
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
738
|
+
function effectiveCa() {
|
|
739
|
+
const path = process.env.NODE_EXTRA_CA_CERTS;
|
|
740
|
+
if (!path) return void 0;
|
|
741
|
+
try {
|
|
742
|
+
return [...rootCertificates, readFileSync4(path, "utf-8")];
|
|
743
|
+
} catch {
|
|
744
|
+
return void 0;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
var PIN_CHECK_ERROR_CODE = "EAS_TLS_PIN_CHECK";
|
|
748
|
+
function taggedCheckError(err) {
|
|
749
|
+
err.code = PIN_CHECK_ERROR_CODE;
|
|
750
|
+
return err;
|
|
751
|
+
}
|
|
752
|
+
function isPinCheckError(err) {
|
|
753
|
+
let cur = err;
|
|
754
|
+
for (let i = 0; i < 5 && cur; i++) {
|
|
755
|
+
if (cur instanceof Error && cur.code === PIN_CHECK_ERROR_CODE) return true;
|
|
756
|
+
cur = cur instanceof Error ? cur.cause : void 0;
|
|
757
|
+
}
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
var AsTlsMismatchError = class extends Error {
|
|
761
|
+
constructor(message) {
|
|
762
|
+
super(message);
|
|
763
|
+
this.name = "AsTlsMismatchError";
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
function spkiSha256Hex(cert) {
|
|
767
|
+
if (!cert.pubkey) {
|
|
768
|
+
throw new Error("peer certificate carries no pubkey (expected the detailed certificate object)");
|
|
769
|
+
}
|
|
770
|
+
return createHash3("sha256").update(cert.pubkey).digest("hex");
|
|
771
|
+
}
|
|
772
|
+
function formatPinFingerprint(hex) {
|
|
773
|
+
const upper = hex.toUpperCase();
|
|
774
|
+
return upper.match(/.{1,4}/g)?.join(":") ?? upper;
|
|
775
|
+
}
|
|
776
|
+
function pinnedCheckServerIdentity(pinnedSpkiHex) {
|
|
777
|
+
const wantHex = pinnedSpkiHex.toLowerCase();
|
|
778
|
+
return (hostname, cert) => {
|
|
779
|
+
const defaultErr = defaultCheckServerIdentity(hostname, cert);
|
|
780
|
+
if (defaultErr) return taggedCheckError(defaultErr);
|
|
781
|
+
let actualHex;
|
|
782
|
+
try {
|
|
783
|
+
actualHex = spkiSha256Hex(cert);
|
|
784
|
+
} catch (err) {
|
|
785
|
+
return taggedCheckError(new Error(
|
|
786
|
+
`could not read the server certificate's public key to check the TLS pin \u2014 ${err instanceof Error ? err.message : String(err)}`
|
|
787
|
+
));
|
|
788
|
+
}
|
|
789
|
+
if (actualHex !== wantHex) {
|
|
790
|
+
return taggedCheckError(new Error(
|
|
791
|
+
`TLS certificate pin mismatch for ${hostname}: expected SPKI sha256 ${formatPinFingerprint(wantHex)}, got ${formatPinFingerprint(actualHex)}.`
|
|
792
|
+
));
|
|
793
|
+
}
|
|
794
|
+
return void 0;
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function buildPinnedDispatcher(pinnedSpkiHex) {
|
|
798
|
+
return new Agent({
|
|
799
|
+
connect: {
|
|
800
|
+
ca: effectiveCa(),
|
|
801
|
+
checkServerIdentity: pinnedCheckServerIdentity(pinnedSpkiHex)
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
function buildCapturingDispatcher() {
|
|
806
|
+
let captured;
|
|
807
|
+
const dispatcher = new Agent({
|
|
808
|
+
connect: {
|
|
809
|
+
ca: effectiveCa(),
|
|
810
|
+
checkServerIdentity: (hostname, cert) => {
|
|
811
|
+
captured = cert;
|
|
812
|
+
const defaultErr = defaultCheckServerIdentity(hostname, cert);
|
|
813
|
+
return defaultErr ? taggedCheckError(defaultErr) : void 0;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
return { dispatcher, getCapturedCert: () => captured };
|
|
818
|
+
}
|
|
819
|
+
function buildPinnedHttpsAgent(getPinning) {
|
|
820
|
+
return new HttpsAgent({
|
|
821
|
+
checkServerIdentity: (hostname, cert) => {
|
|
822
|
+
const pinning = getPinning();
|
|
823
|
+
if (!pinning.enforce) return defaultCheckServerIdentity(hostname, cert);
|
|
824
|
+
if (!pinning.pinnedSpkiHex) {
|
|
825
|
+
return taggedCheckError(new Error(
|
|
826
|
+
`pin-tls is on but no certificate is pinned yet for ${hostname} \u2014 sign in again to establish it (re-pairing required).`
|
|
827
|
+
));
|
|
828
|
+
}
|
|
829
|
+
return pinnedCheckServerIdentity(pinning.pinnedSpkiHex)(hostname, cert);
|
|
830
|
+
},
|
|
831
|
+
ca: effectiveCa()
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
async function fetchAs(url, init, pinning) {
|
|
835
|
+
if (!pinning.enforce && !pinning.capture) {
|
|
836
|
+
const res2 = await fetch(url, init);
|
|
837
|
+
return { res: res2 };
|
|
838
|
+
}
|
|
839
|
+
if (pinning.enforce && !pinning.capture && !pinning.pinnedSpkiHex) {
|
|
840
|
+
throw new AsTlsMismatchError(
|
|
841
|
+
`pin-tls is on but no certificate is pinned yet for ${url} \u2014 sign in again to establish it (re-pairing required).`
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
if (pinning.pinnedSpkiHex && (pinning.enforce || !pinning.capture)) {
|
|
845
|
+
const dispatcher2 = buildPinnedDispatcher(pinning.pinnedSpkiHex);
|
|
846
|
+
try {
|
|
847
|
+
const res2 = await undiciFetch(url, { ...init, dispatcher: dispatcher2 });
|
|
848
|
+
return { res: res2 };
|
|
849
|
+
} catch (err) {
|
|
850
|
+
if (!isPinCheckError(err)) throw err;
|
|
851
|
+
throw new AsTlsMismatchError(
|
|
852
|
+
`TLS pin check failed for ${url} \u2014 ${describeFetchError(err)}. Refusing the connection; the API key / session cookie were never sent. If the Authority Server's certificate changed intentionally (a new key, not just renewal), an operator must clear the pairing and sign in again to re-pin it.`
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
const { dispatcher, getCapturedCert } = buildCapturingDispatcher();
|
|
857
|
+
let res;
|
|
858
|
+
try {
|
|
859
|
+
res = await undiciFetch(url, { ...init, dispatcher });
|
|
860
|
+
} catch (err) {
|
|
861
|
+
if (!isPinCheckError(err)) throw err;
|
|
862
|
+
throw new AsTlsMismatchError(
|
|
863
|
+
`could not verify the Authority Server at ${url} while establishing its TLS pin \u2014 ${describeFetchError(err)}.`
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
const cert = getCapturedCert();
|
|
867
|
+
return { res, capturedSpkiHex: cert ? spkiSha256Hex(cert) : void 0 };
|
|
868
|
+
}
|
|
869
|
+
function describeFetchError(err) {
|
|
870
|
+
if (err instanceof Error) {
|
|
871
|
+
const cause = err.cause;
|
|
872
|
+
if (cause instanceof Error) return cause.message;
|
|
873
|
+
return err.message;
|
|
874
|
+
}
|
|
875
|
+
return String(err);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// src/lib/as-challenge.ts
|
|
879
|
+
var AsChallengeUnreachableError = class extends Error {
|
|
880
|
+
constructor(message) {
|
|
881
|
+
super(message);
|
|
882
|
+
this.name = "AsChallengeUnreachableError";
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
var AsChallengeInvalidError = class extends Error {
|
|
886
|
+
constructor(message) {
|
|
887
|
+
super(message);
|
|
888
|
+
this.name = "AsChallengeInvalidError";
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
var CHALLENGE_MAX_SKEW_SECONDS = 300;
|
|
892
|
+
var CHALLENGE_TYPE = "hap-as-challenge";
|
|
893
|
+
var CHALLENGE_DOMAIN_PREFIX = "hap-as-challenge\0";
|
|
894
|
+
function challengeSigningBytes(unsigned) {
|
|
895
|
+
return Buffer.concat([
|
|
896
|
+
Buffer.from(CHALLENGE_DOMAIN_PREFIX, "utf-8"),
|
|
897
|
+
Buffer.from(canonicalize({ typ: unsigned.typ, nonce: unsigned.nonce, issuedAt: unsigned.issuedAt }), "utf-8")
|
|
898
|
+
]);
|
|
899
|
+
}
|
|
900
|
+
function publicKeyFromHex(publicKeyHex) {
|
|
901
|
+
const raw = Buffer.from(publicKeyHex, "hex");
|
|
902
|
+
return createPublicKey({ key: { kty: "OKP", crv: "Ed25519", x: raw.toString("base64url") }, format: "jwk" });
|
|
903
|
+
}
|
|
904
|
+
function verifyChallengeSignature(publicKeyHex, unsigned, signature) {
|
|
905
|
+
try {
|
|
906
|
+
const base64 = signature.replace(/-/g, "+").replace(/_/g, "/");
|
|
907
|
+
const padding = base64.length % 4 === 0 ? "" : "=".repeat(4 - base64.length % 4);
|
|
908
|
+
const sigBytes = Buffer.from(base64 + padding, "base64");
|
|
909
|
+
const key = publicKeyFromHex(publicKeyHex);
|
|
910
|
+
return cryptoVerify(null, challengeSigningBytes(unsigned), key, sigBytes);
|
|
911
|
+
} catch {
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
async function verifyAsHoldsKey(asUrl, publicKeyHex, pinning = { enforce: false, capture: true }) {
|
|
916
|
+
const nonce = randomBytes2(32).toString("base64url");
|
|
917
|
+
let res;
|
|
918
|
+
let capturedSpkiHex;
|
|
919
|
+
try {
|
|
920
|
+
const result = await fetchAs(
|
|
921
|
+
`${asUrl}/api/as/challenge`,
|
|
922
|
+
{
|
|
923
|
+
method: "POST",
|
|
924
|
+
headers: { "Content-Type": "application/json" },
|
|
925
|
+
body: JSON.stringify({ nonce }),
|
|
926
|
+
signal: AbortSignal.timeout(5e3)
|
|
927
|
+
},
|
|
928
|
+
pinning
|
|
929
|
+
);
|
|
930
|
+
res = result.res;
|
|
931
|
+
capturedSpkiHex = result.capturedSpkiHex;
|
|
932
|
+
} catch (err) {
|
|
933
|
+
if (err instanceof AsTlsMismatchError) throw err;
|
|
934
|
+
throw new AsChallengeUnreachableError(
|
|
935
|
+
`could not reach the Authority Server at ${asUrl} to verify it holds its signing key \u2014 ${err instanceof Error ? err.message : String(err)}`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
if (!res.ok) {
|
|
939
|
+
throw new AsChallengeUnreachableError(
|
|
940
|
+
`the Authority Server at ${asUrl} answered its signing-key challenge with HTTP ${res.status}`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
const body = await res.json().catch(() => null);
|
|
944
|
+
if (!body) {
|
|
945
|
+
throw new AsChallengeUnreachableError(
|
|
946
|
+
`the Authority Server at ${asUrl} returned a malformed response to its signing-key challenge`
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
if (body.typ !== CHALLENGE_TYPE) {
|
|
950
|
+
throw new AsChallengeInvalidError(
|
|
951
|
+
`the challenge response carries the wrong type ("${String(body.typ)}", expected "${CHALLENGE_TYPE}")`
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
if (body.nonce !== nonce) {
|
|
955
|
+
throw new AsChallengeInvalidError(
|
|
956
|
+
"the challenge response echoes a different nonce than the one sent"
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
if (typeof body.issuedAt !== "number" || !Number.isFinite(body.issuedAt)) {
|
|
960
|
+
throw new AsChallengeInvalidError("the challenge response carries no valid issuedAt");
|
|
961
|
+
}
|
|
962
|
+
const skew = Math.abs(Math.floor(Date.now() / 1e3) - body.issuedAt);
|
|
963
|
+
if (skew > CHALLENGE_MAX_SKEW_SECONDS) {
|
|
964
|
+
throw new AsChallengeInvalidError(
|
|
965
|
+
`the challenge response is timestamped ${skew}s away from now, beyond the ${CHALLENGE_MAX_SKEW_SECONDS}s tolerance`
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
if (typeof body.signature !== "string" || !body.signature) {
|
|
969
|
+
throw new AsChallengeInvalidError("the challenge response carries no signature");
|
|
970
|
+
}
|
|
971
|
+
if (!verifyChallengeSignature(publicKeyHex, { typ: body.typ, nonce: body.nonce, issuedAt: body.issuedAt }, body.signature)) {
|
|
972
|
+
throw new AsChallengeInvalidError(
|
|
973
|
+
"the challenge signature does not verify under the key being checked \u2014 this is exactly what the challenge exists to catch: something answered the request but does not hold the matching private key."
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
return { capturedTlsSpkiHex: capturedSpkiHex };
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// src/lib/as-config.ts
|
|
980
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
981
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
982
|
+
var DEFAULT_AS_URL = "https://www.suveren.ai";
|
|
983
|
+
function configPath(dataDir) {
|
|
984
|
+
return join4(dataDir, "config.json");
|
|
985
|
+
}
|
|
986
|
+
function readAsConfigStrict(dataDir) {
|
|
987
|
+
const path = configPath(dataDir);
|
|
988
|
+
if (!existsSync3(path)) return {};
|
|
989
|
+
let data;
|
|
990
|
+
try {
|
|
991
|
+
data = JSON.parse(readFileSync5(path, "utf-8"));
|
|
992
|
+
} catch (err) {
|
|
993
|
+
throw new Error(
|
|
994
|
+
`Could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
const out = {};
|
|
998
|
+
if (typeof data.asUrl === "string") out.asUrl = data.asUrl;
|
|
999
|
+
if (typeof data.caFile === "string") out.caFile = data.caFile;
|
|
1000
|
+
if (typeof data.pinTls === "boolean") out.pinTls = data.pinTls;
|
|
1001
|
+
if (typeof data.pinTlsExpectedFingerprint === "string") out.pinTlsExpectedFingerprint = data.pinTlsExpectedFingerprint;
|
|
1002
|
+
return out;
|
|
1003
|
+
}
|
|
1004
|
+
function readAsConfig(dataDir) {
|
|
1005
|
+
const path = configPath(dataDir);
|
|
1006
|
+
if (!existsSync3(path)) return {};
|
|
1007
|
+
try {
|
|
1008
|
+
const data = JSON.parse(readFileSync5(path, "utf-8"));
|
|
1009
|
+
const out = {};
|
|
1010
|
+
if (typeof data.asUrl === "string") out.asUrl = data.asUrl;
|
|
1011
|
+
if (typeof data.caFile === "string") out.caFile = data.caFile;
|
|
1012
|
+
if (typeof data.pinTls === "boolean") out.pinTls = data.pinTls;
|
|
1013
|
+
if (typeof data.pinTlsExpectedFingerprint === "string") out.pinTlsExpectedFingerprint = data.pinTlsExpectedFingerprint;
|
|
1014
|
+
return out;
|
|
1015
|
+
} catch {
|
|
1016
|
+
return {};
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function writeAsConfig(dataDir, patch) {
|
|
1020
|
+
const merged = { ...readAsConfig(dataDir), ...patch };
|
|
1021
|
+
const path = configPath(dataDir);
|
|
1022
|
+
mkdirSync3(dirname3(path), { recursive: true, mode: 448 });
|
|
1023
|
+
writeFileSync3(path, JSON.stringify(merged, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1024
|
+
return merged;
|
|
1025
|
+
}
|
|
1026
|
+
function validateAsUrl(candidate) {
|
|
1027
|
+
const trimmed = candidate.trim();
|
|
1028
|
+
if (!trimmed) return { ok: false, error: "The Authority Server URL is empty." };
|
|
1029
|
+
let parsed;
|
|
1030
|
+
try {
|
|
1031
|
+
parsed = new URL(trimmed);
|
|
1032
|
+
} catch {
|
|
1033
|
+
return { ok: false, error: `"${trimmed}" is not a valid URL.` };
|
|
1034
|
+
}
|
|
1035
|
+
const isLocalHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
1036
|
+
if (parsed.protocol !== "https:" && !isLocalHttp) {
|
|
1037
|
+
return {
|
|
1038
|
+
ok: false,
|
|
1039
|
+
error: `"${trimmed}" must use https:// (http:// is only allowed for http://localhost or http://127.0.0.1).`
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
let normalized = `${parsed.origin}${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
1043
|
+
if (normalized.endsWith("/") && normalized !== `${parsed.origin}/`) {
|
|
1044
|
+
normalized = normalized.slice(0, -1);
|
|
1045
|
+
} else if (normalized === `${parsed.origin}/`) {
|
|
1046
|
+
normalized = parsed.origin;
|
|
1047
|
+
}
|
|
1048
|
+
return { ok: true, url: normalized };
|
|
1049
|
+
}
|
|
1050
|
+
function resolveAsUrl(dataDir, flag) {
|
|
1051
|
+
if (flag) {
|
|
1052
|
+
const v = validateAsUrl(flag);
|
|
1053
|
+
if (!v.ok) throw new Error(`Invalid --as-url: ${v.error}`);
|
|
1054
|
+
return v.url;
|
|
1055
|
+
}
|
|
1056
|
+
const envUrl = process.env.SUVEREN_AS_URL;
|
|
1057
|
+
if (envUrl) {
|
|
1058
|
+
const v = validateAsUrl(envUrl);
|
|
1059
|
+
if (!v.ok) throw new Error(`Invalid SUVEREN_AS_URL: ${v.error}`);
|
|
1060
|
+
return v.url;
|
|
1061
|
+
}
|
|
1062
|
+
const saved = readAsConfigStrict(dataDir).asUrl;
|
|
1063
|
+
if (saved) {
|
|
1064
|
+
const v = validateAsUrl(saved);
|
|
1065
|
+
if (!v.ok) throw new Error(`Invalid saved as-url "${saved}" in ${dataDir}/config.json: ${v.error}`);
|
|
1066
|
+
return v.url;
|
|
1067
|
+
}
|
|
1068
|
+
return DEFAULT_AS_URL;
|
|
1069
|
+
}
|
|
1070
|
+
function resolvePinTls(dataDir) {
|
|
1071
|
+
return readAsConfig(dataDir).pinTls === true;
|
|
1072
|
+
}
|
|
1073
|
+
function validatePinTlsForUrl(pinTls, asUrl) {
|
|
1074
|
+
if (!pinTls) return;
|
|
1075
|
+
if (!asUrl.startsWith("https:")) {
|
|
1076
|
+
throw new Error(
|
|
1077
|
+
`config.json sets "pinTls": true, but the Authority Server URL (${asUrl}) is not https:// \u2014 there is no TLS certificate to pin. Fix the saved as-url, or turn pin-tls off: \`suveren-gateway config set pin-tls off\`.`
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
function resolvePinTlsExpectedFingerprint(dataDir) {
|
|
1082
|
+
return readAsConfig(dataDir).pinTlsExpectedFingerprint;
|
|
1083
|
+
}
|
|
1084
|
+
function clearPinTlsExpectedFingerprint(dataDir) {
|
|
1085
|
+
if (readAsConfig(dataDir).pinTlsExpectedFingerprint === void 0) return;
|
|
1086
|
+
writeAsConfig(dataDir, { pinTlsExpectedFingerprint: void 0 });
|
|
1087
|
+
}
|
|
1088
|
+
|
|
637
1089
|
// src/routes/auth.ts
|
|
638
|
-
var
|
|
639
|
-
function
|
|
1090
|
+
var DEFAULT_SP_URL = process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai";
|
|
1091
|
+
async function fetchAsPublicKey(asUrl) {
|
|
1092
|
+
try {
|
|
1093
|
+
const res = await fetch(`${asUrl}/api/as/pubkey`, { signal: AbortSignal.timeout(5e3) });
|
|
1094
|
+
if (!res.ok) {
|
|
1095
|
+
return {
|
|
1096
|
+
ok: false,
|
|
1097
|
+
message: `Could not reach the Authority Server at ${asUrl} to read its signing key (HTTP ${res.status}). Refusing to sign in.`
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
const body = await res.json().catch(() => null);
|
|
1101
|
+
if (!body || typeof body.publicKey !== "string" || !body.publicKey) {
|
|
1102
|
+
return {
|
|
1103
|
+
ok: false,
|
|
1104
|
+
message: `The Authority Server at ${asUrl} returned a malformed signing key. Refusing to sign in.`
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
return { ok: true, publicKeyHex: body.publicKey };
|
|
1108
|
+
} catch (err) {
|
|
1109
|
+
return {
|
|
1110
|
+
ok: false,
|
|
1111
|
+
message: `Could not reach the Authority Server at ${asUrl} to read its signing key \u2014 ${err instanceof Error ? err.message : String(err)}. Refusing to sign in.`
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
async function checkAsKeyBeforeLogin(asUrl, dataDir) {
|
|
1116
|
+
const existing = readPairing(dataDir);
|
|
1117
|
+
const pinnedKey = existing && existing.asUrl === asUrl ? existing.publicKeyHex : void 0;
|
|
1118
|
+
const existingTlsPin = (existing && existing.asUrl === asUrl ? existing.tlsSpkiPinHex : void 0) ?? resolvePinTlsExpectedFingerprint(dataDir);
|
|
1119
|
+
let candidateKey;
|
|
1120
|
+
if (pinnedKey) {
|
|
1121
|
+
candidateKey = pinnedKey;
|
|
1122
|
+
} else {
|
|
1123
|
+
const fetched = await fetchAsPublicKey(asUrl);
|
|
1124
|
+
if (!fetched.ok) {
|
|
1125
|
+
return { ok: false, error: "as_unreachable", message: fetched.message };
|
|
1126
|
+
}
|
|
1127
|
+
candidateKey = fetched.publicKeyHex;
|
|
1128
|
+
}
|
|
1129
|
+
const pinning = {
|
|
1130
|
+
enforce: resolvePinTls(dataDir),
|
|
1131
|
+
pinnedSpkiHex: existingTlsPin,
|
|
1132
|
+
capture: true
|
|
1133
|
+
};
|
|
1134
|
+
let capturedTlsSpkiHex;
|
|
1135
|
+
try {
|
|
1136
|
+
const result = await verifyAsHoldsKey(asUrl, candidateKey, pinning);
|
|
1137
|
+
capturedTlsSpkiHex = result.capturedTlsSpkiHex;
|
|
1138
|
+
} catch (err) {
|
|
1139
|
+
if (err instanceof AsTlsMismatchError) {
|
|
1140
|
+
return { ok: false, error: "as_tls_mismatch", message: err.message };
|
|
1141
|
+
}
|
|
1142
|
+
if (err instanceof AsChallengeUnreachableError) {
|
|
1143
|
+
return { ok: false, error: "as_unverified", message: `${err.message}. Refusing to sign in.` };
|
|
1144
|
+
}
|
|
1145
|
+
if (err instanceof AsChallengeInvalidError) {
|
|
1146
|
+
if (pinnedKey) {
|
|
1147
|
+
return {
|
|
1148
|
+
ok: false,
|
|
1149
|
+
error: "as_key_mismatch",
|
|
1150
|
+
message: `The Authority Server at ${asUrl} does not match the one pinned when this gateway last signed in (pinned fingerprint ${fingerprintOf(pinnedKey)}) \u2014 its signing-key challenge did not verify (${err.message}). Refusing to sign in. If the AS's key changed intentionally, an operator must clear the old pairing before signing in again.`
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
return {
|
|
1154
|
+
ok: false,
|
|
1155
|
+
error: "as_unverified",
|
|
1156
|
+
message: `The Authority Server at ${asUrl} could not prove it holds the signing key it presented \u2014 ${err.message}. Refusing to sign in.`
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
throw err;
|
|
1160
|
+
}
|
|
1161
|
+
return {
|
|
1162
|
+
ok: true,
|
|
1163
|
+
publicKeyHex: candidateKey,
|
|
1164
|
+
// A fresh capture (always present for https, unless pin-tls is on and
|
|
1165
|
+
// an existing pin was enforced instead — see fetchAs) wins; otherwise
|
|
1166
|
+
// whatever was already on file carries through unchanged.
|
|
1167
|
+
tlsSpkiPinHex: capturedTlsSpkiHex ?? existingTlsPin
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablished, pairing, lockAsTlsMismatch2 = () => {
|
|
1171
|
+
}) {
|
|
640
1172
|
const router = Router();
|
|
1173
|
+
const SP_URL2 = pairing?.asUrl ?? DEFAULT_SP_URL;
|
|
641
1174
|
router.post("/login", loginRateLimit2, async (req, res) => {
|
|
642
1175
|
const apiKey = req.headers["x-api-key"] || req.body?.apiKey;
|
|
643
1176
|
const confirmWipe = req.body?.confirmWipe === true;
|
|
@@ -646,22 +1179,65 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
|
|
|
646
1179
|
return;
|
|
647
1180
|
}
|
|
648
1181
|
try {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
"
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
1182
|
+
let keyCheck = null;
|
|
1183
|
+
if (pairing) {
|
|
1184
|
+
keyCheck = await checkAsKeyBeforeLogin(pairing.asUrl, pairing.dataDir);
|
|
1185
|
+
if (!keyCheck.ok) {
|
|
1186
|
+
const status = keyCheck.error === "as_key_mismatch" || keyCheck.error === "as_tls_mismatch" ? 409 : 502;
|
|
1187
|
+
res.status(status).json({
|
|
1188
|
+
error: keyCheck.error,
|
|
1189
|
+
message: keyCheck.message
|
|
1190
|
+
});
|
|
1191
|
+
return;
|
|
658
1192
|
}
|
|
659
|
-
}
|
|
1193
|
+
}
|
|
1194
|
+
const sessionPinning = {
|
|
1195
|
+
enforce: Boolean(pairing && resolvePinTls(pairing.dataDir)),
|
|
1196
|
+
pinnedSpkiHex: keyCheck?.tlsSpkiPinHex
|
|
1197
|
+
};
|
|
1198
|
+
let spRes;
|
|
1199
|
+
try {
|
|
1200
|
+
const result = await fetchAs(
|
|
1201
|
+
`${SP_URL2}/api/auth/session`,
|
|
1202
|
+
{
|
|
1203
|
+
method: "POST",
|
|
1204
|
+
headers: {
|
|
1205
|
+
"Content-Type": "application/json",
|
|
1206
|
+
"X-API-Key": apiKey,
|
|
1207
|
+
// The AS grants a 30-day gateway session ONLY to a login that
|
|
1208
|
+
// identifies itself this way; without it, a 24-hour browser
|
|
1209
|
+
// session (see doc at the top of this file).
|
|
1210
|
+
...clientVersionHeaders()
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
sessionPinning
|
|
1214
|
+
);
|
|
1215
|
+
spRes = result.res;
|
|
1216
|
+
} catch (err) {
|
|
1217
|
+
if (err instanceof AsTlsMismatchError) {
|
|
1218
|
+
res.status(409).json({ error: "as_tls_mismatch", message: err.message });
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
throw err;
|
|
1222
|
+
}
|
|
660
1223
|
if (!spRes.ok) {
|
|
661
1224
|
const err = await spRes.json().catch(() => ({ error: "Invalid API key" }));
|
|
662
1225
|
res.status(spRes.status).json(err);
|
|
663
1226
|
return;
|
|
664
1227
|
}
|
|
1228
|
+
if (pairing && keyCheck?.publicKeyHex) {
|
|
1229
|
+
const existing = readPairing(pairing.dataDir);
|
|
1230
|
+
if (!existing || existing.asUrl !== pairing.asUrl) {
|
|
1231
|
+
writePairing(pairing.dataDir, pairing.asUrl, keyCheck.publicKeyHex, {
|
|
1232
|
+
tlsSpkiPinHex: keyCheck.tlsSpkiPinHex
|
|
1233
|
+
});
|
|
1234
|
+
console.error(`[Control Plane] Paired with Authority Server ${pairing.asUrl} (fingerprint ${fingerprintOf(keyCheck.publicKeyHex)})`);
|
|
1235
|
+
} else if (keyCheck.tlsSpkiPinHex && keyCheck.tlsSpkiPinHex !== existing.tlsSpkiPinHex) {
|
|
1236
|
+
recordTlsPin(pairing.dataDir, pairing.asUrl, keyCheck.tlsSpkiPinHex);
|
|
1237
|
+
console.error(`[Control Plane] TLS pin for Authority Server ${pairing.asUrl} captured/updated.`);
|
|
1238
|
+
}
|
|
1239
|
+
clearPinTlsExpectedFingerprint(pairing.dataDir);
|
|
1240
|
+
}
|
|
665
1241
|
const data = await spRes.json();
|
|
666
1242
|
const setCookieHeaders = spRes.headers.getSetCookie?.() ?? [];
|
|
667
1243
|
const sessionCookie = setCookieHeaders.join("; ");
|
|
@@ -708,10 +1284,11 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
|
|
|
708
1284
|
const kp = await loadOrGenerateKeyPair(vault2);
|
|
709
1285
|
const localPubkeyB64 = Buffer.from(kp.publicKey).toString("base64");
|
|
710
1286
|
const spCookie = vault2.getSpCookie();
|
|
711
|
-
const meKeyRes = await
|
|
712
|
-
|
|
713
|
-
signal: AbortSignal.timeout(5e3)
|
|
714
|
-
|
|
1287
|
+
const { res: meKeyRes } = await fetchAs(
|
|
1288
|
+
`${SP_URL2}/api/users/me/pubkey`,
|
|
1289
|
+
{ headers: spCookie ? { Cookie: spCookie } : {}, signal: AbortSignal.timeout(5e3) },
|
|
1290
|
+
sessionPinning
|
|
1291
|
+
);
|
|
715
1292
|
let needsUpdate = false;
|
|
716
1293
|
if (meKeyRes.status === 404) {
|
|
717
1294
|
needsUpdate = true;
|
|
@@ -720,15 +1297,19 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
|
|
|
720
1297
|
needsUpdate = meKeyData.pubkey !== localPubkeyB64;
|
|
721
1298
|
}
|
|
722
1299
|
if (needsUpdate) {
|
|
723
|
-
const putRes = await
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1300
|
+
const { res: putRes } = await fetchAs(
|
|
1301
|
+
`${SP_URL2}/api/users/me/pubkey`,
|
|
1302
|
+
{
|
|
1303
|
+
method: "PUT",
|
|
1304
|
+
headers: {
|
|
1305
|
+
"Content-Type": "application/json",
|
|
1306
|
+
...spCookie ? { Cookie: spCookie } : {}
|
|
1307
|
+
},
|
|
1308
|
+
body: JSON.stringify({ pubkey: localPubkeyB64 }),
|
|
1309
|
+
signal: AbortSignal.timeout(5e3)
|
|
728
1310
|
},
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
});
|
|
1311
|
+
sessionPinning
|
|
1312
|
+
);
|
|
732
1313
|
if (!putRes.ok) {
|
|
733
1314
|
console.error(`[Control Plane] E2EE pubkey registration failed: ${putRes.status}`);
|
|
734
1315
|
} else {
|
|
@@ -738,7 +1319,12 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
|
|
|
738
1319
|
console.error("[Control Plane] E2EE pubkey already up to date");
|
|
739
1320
|
}
|
|
740
1321
|
} catch (err) {
|
|
741
|
-
|
|
1322
|
+
if (err instanceof AsTlsMismatchError) {
|
|
1323
|
+
console.error("[Control Plane] E2EE pubkey auto-register aborted \u2014 TLS pin mismatch:", err.message);
|
|
1324
|
+
lockAsTlsMismatch2();
|
|
1325
|
+
} else {
|
|
1326
|
+
console.error("[Control Plane] E2EE pubkey auto-register failed:", err);
|
|
1327
|
+
}
|
|
742
1328
|
}
|
|
743
1329
|
for (const credId of vault2.listCredentials()) {
|
|
744
1330
|
try {
|
|
@@ -775,12 +1361,20 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2, onSessionEstablis
|
|
|
775
1361
|
router.post("/logout", logoutAuth, async (_req, res) => {
|
|
776
1362
|
const cookie = vault2.getSpCookie();
|
|
777
1363
|
vault2.clearKey();
|
|
1364
|
+
const logoutPinning = pairing ? { enforce: resolvePinTls(pairing.dataDir), pinnedSpkiHex: readPairing(pairing.dataDir)?.tlsSpkiPinHex } : { enforce: false };
|
|
778
1365
|
await Promise.allSettled([
|
|
779
1366
|
unconfigureSession(),
|
|
780
|
-
cookie ?
|
|
781
|
-
|
|
782
|
-
headers: { cookie, ...clientVersionHeaders() },
|
|
783
|
-
|
|
1367
|
+
cookie ? fetchAs(
|
|
1368
|
+
`${SP_URL2}/api/auth/logout`,
|
|
1369
|
+
{ method: "POST", headers: { cookie, ...clientVersionHeaders() }, redirect: "manual" },
|
|
1370
|
+
logoutPinning
|
|
1371
|
+
).catch((err) => {
|
|
1372
|
+
if (err instanceof AsTlsMismatchError) {
|
|
1373
|
+
console.error("[Control Plane] Logout: TLS pin mismatch talking to the Authority Server \u2014 local sign-out still applied:", err.message);
|
|
1374
|
+
lockAsTlsMismatch2();
|
|
1375
|
+
} else {
|
|
1376
|
+
throw err;
|
|
1377
|
+
}
|
|
784
1378
|
}) : Promise.resolve()
|
|
785
1379
|
]);
|
|
786
1380
|
res.json({ ok: true });
|
|
@@ -1392,18 +1986,18 @@ async function testAIConnectivity(config) {
|
|
|
1392
1986
|
}
|
|
1393
1987
|
|
|
1394
1988
|
// src/lib/agent-brief-store.ts
|
|
1395
|
-
import { existsSync as
|
|
1989
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
1396
1990
|
import { homedir as homedir2 } from "os";
|
|
1397
|
-
import { join as
|
|
1991
|
+
import { join as join5 } from "path";
|
|
1398
1992
|
var AGENT_CONTEXT_MAX_BYTES = 16 * 1024;
|
|
1399
1993
|
function agentBriefPath() {
|
|
1400
|
-
const dataDir = process.env.SUVEREN_DATA_DIR ??
|
|
1401
|
-
return
|
|
1994
|
+
const dataDir = process.env.SUVEREN_DATA_DIR ?? join5(homedir2(), ".suveren");
|
|
1995
|
+
return join5(dataDir, "context.md");
|
|
1402
1996
|
}
|
|
1403
1997
|
function readAgentBrief() {
|
|
1404
1998
|
const filePath = agentBriefPath();
|
|
1405
|
-
if (!
|
|
1406
|
-
return
|
|
1999
|
+
if (!existsSync4(filePath)) return "";
|
|
2000
|
+
return readFileSync6(filePath, "utf-8");
|
|
1407
2001
|
}
|
|
1408
2002
|
|
|
1409
2003
|
// src/routes/ai.ts
|
|
@@ -1767,28 +2361,28 @@ function createMCPRouter() {
|
|
|
1767
2361
|
// src/routes/autostart.ts
|
|
1768
2362
|
import { Router as Router6 } from "express";
|
|
1769
2363
|
import { execFile } from "child_process";
|
|
1770
|
-
import { existsSync as
|
|
2364
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1771
2365
|
import { dirname as pathDirname, resolve } from "path";
|
|
1772
2366
|
import { fileURLToPath } from "url";
|
|
1773
2367
|
import { promisify } from "util";
|
|
1774
2368
|
var run = promisify(execFile);
|
|
1775
2369
|
var SUPPORTED = /* @__PURE__ */ new Set(["darwin", "win32", "linux"]);
|
|
1776
2370
|
var MODULE_DIR = pathDirname(fileURLToPath(import.meta.url));
|
|
1777
|
-
function findCli(
|
|
2371
|
+
function findCli(dirname9 = MODULE_DIR) {
|
|
1778
2372
|
const candidates = [
|
|
1779
2373
|
// Bundled (the shipped layout): dist/control-plane → dist → root → bin
|
|
1780
|
-
resolve(
|
|
2374
|
+
resolve(dirname9, "..", "..", "bin", "suveren-gateway.js"),
|
|
1781
2375
|
// Bundled, were the routes/ directory ever preserved.
|
|
1782
|
-
resolve(
|
|
2376
|
+
resolve(dirname9, "..", "..", "..", "bin", "suveren-gateway.js"),
|
|
1783
2377
|
// Dev, running from source: the repo's own bundle directory.
|
|
1784
|
-
resolve(
|
|
1785
|
-
resolve(
|
|
2378
|
+
resolve(dirname9, "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js"),
|
|
2379
|
+
resolve(dirname9, "..", "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js")
|
|
1786
2380
|
// Deliberately NO process.cwd() fallback: it makes the result depend on
|
|
1787
2381
|
// where the process happened to be launched from, so the same install
|
|
1788
2382
|
// resolves differently between a shell and a login service — and it would
|
|
1789
2383
|
// mask a genuinely missing CLI whenever the cwd happened to be the repo.
|
|
1790
2384
|
];
|
|
1791
|
-
return candidates.find(
|
|
2385
|
+
return candidates.find(existsSync5) ?? null;
|
|
1792
2386
|
}
|
|
1793
2387
|
async function cli(args) {
|
|
1794
2388
|
const bin = findCli();
|
|
@@ -1869,17 +2463,17 @@ function createAutostartRouter() {
|
|
|
1869
2463
|
import { spawn, spawnSync } from "child_process";
|
|
1870
2464
|
|
|
1871
2465
|
// src/lib/notifier-icon.ts
|
|
1872
|
-
import { writeFileSync as
|
|
2466
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync6 } from "fs";
|
|
1873
2467
|
import { homedir as homedir3 } from "os";
|
|
1874
|
-
import { join as
|
|
2468
|
+
import { join as join6, dirname as dirname4 } from "path";
|
|
1875
2469
|
var ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAACXBIWXMAACxLAAAsSwGlPZapAAAaEElEQVR42u2deXxNV9fH7/O2z/vHk+HmJoIoQQxpBtVPi+LTIWZqeDQ6V0tRFUWIeagSRAheyasxVNUsWtRQSquoMTRi9mgJooZWhBqaSIX97nWa9CVN4ubes8/Z55zf+ny+H1rknrv3Wr+zh7XXttmMaY94e3vXdDgcL3JifHx8ZnE2cvbw/z7MyeBc5eRxGABukFfgS+RTh8nHCnxtFvke+SD3xRrkkzaYGPP19fXmDd6eM403eDoCG0gqFPu5j07ltCOfReS6YbwRn+ANGsd/TeW/5sPBgMG4U+C7Ezh1ENFOGB9K+fLG6skbbiccCJgJ7tPH+K9D/f39KyLS/z7Eb84baD2pJpwFWGBksN5utzezetz/o2BevwdOASxKOn/5vUKxYKnA51/8tYLVejgBAA7HQUsIgZ+fXzB/43+LDgegWLZzwk0X+AEBAf/iX2wMtu8AePgaASeRvyy9zLKd147zMzoWgDLtGpzjv7Y1cuw/WvDWv4sOBcAl7tFogMfSfxsq8vlDB3IF240OBEAVfuDbhkGGCH7+oB35A19DpwGgKlf5S7WD7PP9DzDkB0DolCBG1mH/UHQQAJosEMZLdTS34GgkOgcA7fiMFtplCP7P0RkA6DISWK5nHQLK5Z+DjgBAVxGYrdecfwI6AAApGKv1an9vNDoAUo0EorXc58dWHwBycZeO1wvP8ONko7EBkDNZiL+gq4mK/38ivRcA6acCe4WcHeA//H/QwMAM+Po6WKNQH9arlZ0ldPZmKwZ4sfQ4T/afKZ7s4gwP9tsnf0K/p/+3f4Kn8ncm879L/4b+Lf0MiUVgstqLfu0L0hDhQMCQVK3kYL1be7Pl0V7sXJIH+32ee9DPSOE/K6qVt/KzJUwZflHNYh5n4UTAaPjxt/TLje3s8/5e7OocT7eDviToZ5MYdOKfJcvIgOoJ8ArEnmq8/afAmYCRKOfnYN2a2dmBOHFBXxI0lXi3qV15BgnaYqK78/4wzh9wKmAU6C18ZJKH5oFflCOTPNlLjex6t0ceLzYa4k713q1wKmAEQqr5sAW9vXQP/KKsHujF6gT56Nk237tUbdjxZ+luOBeQnjeft7NLH3tIF/yF/Jrswbo21W80wHMDIl15+6NuP5Caiv4+bGYPL2kDvygfd/fiz6xLWx0o0yiAL/z9Gw4GZN/W2/qhp2GCv5AdH3mxoMq6tNmLZRGAXXAyICu1A33YD+ONF/yF0O5EaDUfrbcF9zh9USecDMjK41V92PEE4wZ/IfQd6LtovBbQxJm3/3o4GpB12E9puUYP/kLS+ChG4yzCdaUGf/ny5Ss4cEU3kHTBz4hz/oexZZSnlguDdyjGS9v6GwhnAzIy6z1v0wV/ITO6eclROIT/hYNwNiAbb0fYTRv8hbyrXZ5AWknBHw5nA7IRzrPoKJHG7AJAiUwa7gzUQZFPYAjoHL7Zg78QOqqsUbvGFrf6vxcOB2SiY0O7ZYK/EDrMpME6wK6ib387Jx9OB2Q60ivDqT6tORzvqcVR4js838e7aMUfOB6QBjrPb7XgL6RLE7u2qcFcAKbB6YBMNfv0KOYhU4KQ6MpCPOYT7p8CpMPxgCxQGS+rBn8hkeKLify1HfgI/4/bcDwgC1TDz+oCsLSv8B2B28rFot7e3jXhdEAWAgMcLHu2p+UFgAqNij4nwA8HVafhf1s4HpAFKt1t9eAv5P2WwqcBrUkAYuB4QBYoGQbBr800QDkXQPeLw/GALKv/alzaYRYyEz1E7wYkkwBshPMBGWjMr9xC4D9IwxAfkSOADSQAe+B8QAbo3j0E/YO818IuUgB2kgAcgfMBGaCLOhH0DxL/prfINj9kw71/QBZWDsACYFG+GCB0IfA0CUA2nA84Q+XKldnzzz/POnbsyFq2bMlCQ0NV/flp47H/X5R94zxF9mkWCUAenBuUFvQjRoxg6enpLD8/nxW1ixcvstmzZ7MGDRq4/Vk/ToUAFOU/UzzFZgPCyUFJREVFsezsbOaM3b17ly1dupSFhIS4/HkXZiDgi/Lz/3oI7WMIAPj7Wfxy5di8efOYK5aTk6P8e1c+99ocBPzfU4IhAEDTZBxftmTJEuaOVahQAQIAAQBGZPDgwcxdCwoKwhQAUwDgDvwCBxYREcHeeOMN1rVrV2Xl3Z35tTPUrl2b3bp1y20BeOKJJ7AIaIxFQAiAdIUweaCvWbOG5ebmFhtcp06dYhMnTmQ1atRQ/bOnTZvG1LDGjRtjG9AY24AQABnw9/dnPXr0YIcOHXI6yG7cuMFiYmKUObtac//z58+rIgAtWrRAIpAxEoEgAHry2GOPsWHDhrHMzEyXgy0lJcXlRbf7oX18teydd95BKrAxUoEhAHpQsWJFNnbsWHb16lVVAo5EwN2RAAWtWjZu3DgcBjLAYSAIgA7Qot7p06eZ2jZo0CC3nmvAgAGqPcuyZctceoZGOA78N54J8YEAmIGGDRuyrVu3MlF28+ZNtxYG+/Tpo9qzpKWluVwQhIpgIPALCoIkiS8PDgEQXeQyMJDNnDmT/fHHH0y0xcfHu/ycnTp1Uu05fvvtN5QEU4El4isDQwBEQifmzp49y7SyjIwMl5+1Vq1a7N69e6o9i6uHg6JaYSFQw6KgEABRufRjxozR5K1f1MLCwlx+7r1796r2HAMHDkRZcDfLglNbQAAMBmXB7dmzh+llNJR35/SfWrZ69WpMA+S+GAQCoDZdunRR5r96Wvfu3d1KSDp+/Lgqz3HlyhXm5+fn2noErgZjLzWyQwCMxPDhw5Uz8Xpb586d3foedP7g9u3bqjwL/SxXdwPSLXw56A8aXA4KAVAxjXfhwoVMFmvatKnb34mSgtRYv0hKSnL5Gd618PXg70TYNfNfCIAbVKlShW3evFma4Kc3N2UZqvHdaC3B2WpAJdmlS5dcLg5Szs/Bjkyy3ijgULwn8/N1QABk5/HHH2cHDx5kMtm6detU/Y7BwcFs5cqVbm0PRkZGuvz5/37GjmvBIQDyER4erun+vrP20ksvCfm+bdq0YQcOHHDpmZYvX+7WZ3/R3zqjgJRoL819GQLgQtEMOpMvm23btk3o96YV/b59+7LLly+X6bmorgG1maufG1bdh/2SbP7gv/SxBwup5gMBkBnKtT927Jh0wU9zdVer8LiS2kyLe3l5eU4/X2Jioluf2fkF808F3nrBRxefhgA4SdWqVZXa+LIZFQZp1aqV5u1Rr149tmHDBqee8ffff2c1a9Z06/M+7m7e5KDErl66+TUEwAkqVarEUlNTpQt+yv1/7rnndG0bWnc4ceKE0INKSg0Ffwf7bpT51gM2j/BkFfwdEACZWbVqlVSBf/36dTZ58mRFmGTJhejfvz/Lysoq8ZmvXbvmdh3DqpXMVTeQEn60yPeHALjBqFGjpAl82lf/6KOPlOmIrGskc+fOZXfu3Cn2+Slhyu3t16o+7HiC8UXg2GQPFhzoo3ufQQBKoUOHDiU6s5ZGuw6UaqxWko9oqCow7UoUd30YHZF2eyeGBw5VyzVq8FOasx4r/hCAMu71l3XLS8Qb//3331et8q8M5c9oF4WmDG4vylYy5prA5pH6D/shAE4U7dRzxZ/y8GfNmqVsuZmlACqVLCu00aNHq/Oz+eLZjG7G2B249akHS3rXS9cFPwiAk8yYMUO34N+xYwd76qmnTJk6TXcO0jSABE7Nrcs3nrezixJfK/ZrsrYHfCAAbtCsWTOWn5+veeDTWgNtlbl6eMYo0GnFffv2KZeQqHm7ES0OLugt32hg9UAvFh7kI21/QADugy7YUKsgRlmMLgZp3bq15cqjL1iwQPX1jY4N7exwvKcUp/raN7BL3w8QgPugvXWtjY4T07Fiq96M1L59e/XPLfDjtF2b2nXJGaC9fRrua3mkFwKgAs8++6zmRTwXL16s3AKMugpiBJCq6tDx2mX9vIQWGqWfTTX8qIyXr6+x2h4CUHDSTctVfzpfHxsbC+HV8n6GgD+vHqNApQs33A36s4meSt3+nrx0d5UA47YLBIBDN/NqGfyUNot21w96S9OVWxS8k97yVm7gpcQiyjC8wHcTrs35E/o9/b+9/M/o79BFnXRXn+jruiAAGkJDcDpUo5WptQcOAARABWJiYjQL/gkTJsDpAARAFgICApR0Wy0sOTkZDgcgADJB13dpYd9//70q+e8AQABULPLhbtlrZ+zcuXNuV8MBAAKgMv369dOkTr8aF3UAAAFQGVfLXJfFRo4cCScDEADZoLx70ZaWlmb6gz0AAmBIVqxYIXzo36hRIzgYgAA4JLzYoyw17V2xuLg4OBeAAMgIFdUUaRcuXDBM7T4ALCcA+/fvFyoAtLsAxwIQAAkJCQlx66ZbZ6r3IuEHQAAkZdCgQULf/t26dYNTAQiArBRXq14t+/nnn7HtByAAslK9enWhFX/oXAEcSj5IlKkCMY3+qOTb1KlT2YgRI1jHjh2Vw2AQAIt80ffee0/ovj/y/eWiVq1abPr06aVe7nLr1i2lLNvTTz8NATA7dGedKFu6dCmCTjKxp8tInTXKCxk/frxSGg4CYFIOHjwoTABoOInAk4OEhASX+3Ht2rVKaXgIgAmP/oq65PPq1auo7Oswz03Oy5YtgwCYjXbt2mH4b3JeeOEF1RZ5o6KiIACo/OOcde7cGQEoAbt371atT2nhkEaNEACTQHM7Uff50e02CEB9admypep9O2DAAAiAWTh58qQQAaCFRQSg/sycOVP1vt2+fTsEwGGKSyB8WW5urhAB+OSTTxCAJq3ulJOTY4lzHaYXgODgYGHz/169eiEAJeD69etC+rdu3boQAKPTvHlzYQJQr149BKAEI7y7d+8K6d8WLVpAAIwOndATYfn5+Tj6Kwk3b94U0sdvvfUWBAAVgEo+/Yfgk4MzZ84I6WMrXOJqegGYM2eOEOegfWcEnxzs27dPSB9PnDgRAmB0lixZIsQ5UlJSEHyS8NVXXwnpYzpABgFwoAR4cZaUlITgk4R58+YJ6WNKIIMAGJx169YJcQ4qLoHgk4P4+HghffzNN99AAIwOdaIIGzduHIJPEmJjY4X08aZNmyAARoeu5sa9fxAAV2zjxo0QAKOTmpoqxDkGDx6M4JMEGo2JsK+//hoCAAHACEB2qJyXCNuwYQMEwOjQPE6EUekpBJ8c0H69CFu/fj0EwOgsX74cJwGR7OWS0Q4SBADOUax98cUXCD6TF3xZuHAhBMDo0H69CNuyZQuCTxL27t2LXA8IQPHQYp0Iy8zMRPBJwrlz54T0cUxMDATA6PTp00eIc9AZdNQD1B+q408Xe6DgKwSgWOjSDlFGpagRhPoSEREhrH+bNWsGATA6oaGhwhyErqBCEOpLv379hPVveHg4BAA140q25ORkBKHO0HasCKNLRqxwTZglBCAtLU2Ikxw5cgRBaNJiIEePHmUoC46iIKXavXv3lGuoEYj6UL16dWF3PtK14RAAB+oCPsy6du2KYNSJHj16COvXoUOHQgDMwmuvvSbMUebPn49gNFmaN1mbNm0gAGahWrVqShlvEZaVlYXrwXWgXLly7MqVK8JyPCpXrgwBMBPp6enC3havv/46gtJE+R0//fQTw/XgJiMxMVGYw3z55ZcISo2hNhdln332GQTAbERGRgpzmNu3byvTDASmNtDOi6j0X7I333wTAmA2KlWqpASqKBsyZAiCUyNGjRolVMytdMbDZiXH2bFjhzDHoRNpWAwUD93HmJGRIawfN2/ebKn2tJQAjB07lom0Dz74AEEqmN69ewvtQ6uN5CwlAHXq1BF2lTTZyZMnmZ+fHwJV4NbfqVOnhArAk08+CQHANMB16969O4JVEH379hXad4cPH7Zcm1pOAEQVCGH3XRuOQiFiFnFFVf5hFr7rwXICEBgYyHJycoQ60tSpUxG0BsrjIMvNzVUOF0EALMCqVauEOhPtUdevXx+BqxKNGzdWzueLtKVLl1qybS0pAK+++ioTbdu2bWO+vr4IYDehRVVRZ/7vt9atW0MArLSaTCv2om306NEIYjf58MMPhffTiRMnLNu+Nqt+cdGLgYVlpZo3b45AdhF6K4se+ls9i9OyAkBZe6JXlQt3BYKCghDQLuT7X7x4UXj//PLLLywgIAACYEVI+bUwumeeUlgR2M5P0bZu3apJ31j9DIelBaBixYrKG0ALs8I9c2pAC6cLFizQpE8uXbpk6be/5QVAi/MB9xtdY40gL51p06Zp1h9WuPoLAvAQqPTThQsXNHE4qiIcHR2NQC+B4cOHaxb8tP5jhbr/EAAnoMq+WhmJADk62v1BqAqvyINaRa1Xr15odwjA/0PnwLW06dOno90L5vzx8fGatv3OnTuRpAUBeJAGDRoILTNVnM2ePVtZ8bZycY9FixZp2uZU8adevXrweQjA36G3stZGKcNWvF2oZs2amo+6yOLi4uDrEIDioWO858+f19wp6TNbtGhhmXZu1aqVLu38448/YuEPAlA67du3F3aJyMNOEI4YMcLUFYVo3k25/Vqk97JiLvto27YtfBwC8HAmTZrE9LJDhw6xiIgI07UpzbtpuqOXTZkyBb4NAXA+FZVWivUyGg1MnjxZyVQ0QyUfWlvR461faFQGzsqLrRAAFwgLCxN291xZklWoDp4RzxFQwNFee2Zmpq5t+Ouvv7Lg4GD4NASg7LzyyitK4o7eRkHUv39/Q7zFaA2DEqu0qLfwMKO1HLpDEL4MAXAZGorLYqdPn1aKjNAWmmztREeeKZuPnlEWi42NhQ9DANxfuV68eDGTySiZ5fPPP1d2LPQcFdBnv/zyy8pFnSKvXXPFUlJSkO0HAVCveMi3337LZLTs7GzF2bt06cKqVKmiSQIP3X2wZMkSzY5Sl9U2bdqEa9ogAOqfGkxPT2cyG+0e7N+/n82dO1e5poyq6bozQqDEqKZNmyrl05KTk5Xvr+WBHVcsNTVV2XmAz0IAVKd27dpSzXGZk3UJqSwZBcbKlSuVQKZ1jTFjxjxAQkIC+/TTT9natWuVLVD6nrIHe1E7fvy4JWv7QwA0hO6OO3PmDIPJZWfPnmUhISHwUQiAeGhf+ejRo4g6SYxy/MPDw+GbEADtoKGmFhdWwEo3WvOQcVsUAmCR04NbtmxBFOpkdLaAFmfhixAAXSsL08IZTFtbtmwZSq1DAORJFqKVdD2OEVvNqI2pujKSfCAA0kHnzenwCUyMZWVlsU6dOsHXIADyEhoaquy5w9S1Xbt2YZsPAmCc1GFKuDFaIo2MRm1IxTxwnh8CYMjad3T1NMw1y8jIwHFeCIDxRwO0QCjbaTnZ05epipAZKiJBAMBfNfG2b9+O6GYPv7TjmWeegc9AAMwHVcuJiorCWQJW/E29PXv2hJ9AAKwxLSAhoAMsVrfLly8rUySrX9MNAbAgdEkF1fqTtbAGE3wZCl2SisCHAOBMAT9TMHDgQEucMKQ6A/RdscAHAQDF0KRJEzZ//nyWk5NjmqCnHZDVq1crW3pI4YUAACdr79E1WnRTkFGNjktHR0ezwMBA9CkEALhKnTp12ODBg5Wjx1pfYV4Wy83NZd999x0bOXIkq1+/PvoOAgDUht6mdPHGokWL2LFjx3Q/gUh1+GbMmMEiIyOxoAcBAHosILZp00a5WXjFihXs1KlTQu7hu3HjhjKkp/WJIUOGsA4dOrAaNWqgDyAAQMaEIzo517x5c/b222+zYcOGsaSkJOUyEVqMI9asWaNU1CmEhu7057NmzWJxcXFs0KBBykiDLh+pW7cu2tXEApCHhgDAktwmAchGQwBgSbJIAM6iIQCwJKdtPj4+R9AQAFiSQyQAu9EQAFgPHvs7SQA2ojEAsKQAbCABmI3GAMCSJNMiYAwaAgBLjgCiSQDaojEAsCStbd7e3jXQEABYD7vdXs3G7RHKCEKDAGCp4X8uxT4JAE0D0tEoAFiKNFuhcTWYigYBwFIjgMn3C0A7NAoAlqLNXwLAj4968f9xB40CgCW4QzFvu9/4KCAVDQOARVKAixr/g/FoHAAsQWxxAhCGhgHAEoTbijP+BwfQOACYmh9sJRnOBQBg+vl/vxIFwMPDozx2AwAw7+o/v5i2gq004wqxHg0FgClZa3uY8QMCzdBQAJjy8E+EzRnjo4BdaDAATDX332Nz1vhfbo9GA8Ckqb9O2D/4P9iPRgPAFBygmC6LANj4Pe6voOEAMMXcv6PNBaNRwBY0IACGZluZ3/73jQJC+Q/4A40IgCHJ4zEcYnPHqHAAGhIAQzLB5q4FBAT8i/+gM2hMAAxFZoUKFTxsapjjz9Lh99CoABiCe0rJbzWNTwWmoGEBMETST7xNgD2KDEEApA/+VB6r/xQhADQVqMK5goYGQEqucgGoahNp/AM68A+6i8YGQCryOS/atDD+Qb3Q4ABINfTva9PS+IeORcMDIEXwj7bpYfzDk9ABAOga/LNsOtoj/AGWoyMA0CX4U/664FNnEZiJDgFAU+bR1rxNFuMPNBSdAoBxE33U2CLsjS1CAIRu9fWyyWwF5cSy0VkAqMoVzfb51cgYpAsI0WkAqDLk38er+lS3Gcwe5Q8/BlMCANw61ZcoLLdfo9HAi3Q2GZ0JQJk4q/qRXr2soKgIjQZuo2MBKBUqwZfo7+/vaTObeXl51eLzmU3oZACKZRsnzGZ24wsakfyLpqPDAVDY72rpbkMb/+LPcr6DAwCLru7vom1zl8t2m2hE0IQ3yDoHriYH5od8fB35vA32oHl7e/vyxumJHAJgwrf9MUqXL1++fAVEunPTgzBOLG+43RgZACO+6QtqaI6lC3YQ0W6Yn5+fF+UTFFQmTsN2IpAQ8skfuI8mkK+achtPInuEz6GCKFGC/9qfjiNzvi5Q3IOcjILzCHlwTOAmeQW+RD51kKan5Gv898n81+gCH6Q03f8yYiD9H4Lpi7OZQSaFAAAAAElFTkSuQmCC";
|
|
1876
2470
|
function ensureNotifierIcon(dataDir) {
|
|
1877
2471
|
try {
|
|
1878
|
-
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ??
|
|
1879
|
-
const path =
|
|
1880
|
-
if (!
|
|
1881
|
-
|
|
1882
|
-
|
|
2472
|
+
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join6(homedir3(), ".suveren");
|
|
2473
|
+
const path = join6(dir, "notifier-icon.png");
|
|
2474
|
+
if (!existsSync6(path)) {
|
|
2475
|
+
mkdirSync4(dirname4(path), { recursive: true });
|
|
2476
|
+
writeFileSync4(path, Buffer.from(ICON_BASE64, "base64"));
|
|
1883
2477
|
}
|
|
1884
2478
|
return path;
|
|
1885
2479
|
} catch {
|
|
@@ -2081,24 +2675,24 @@ import { Router as Router9 } from "express";
|
|
|
2081
2675
|
|
|
2082
2676
|
// src/routes/approved-intents.ts
|
|
2083
2677
|
import { Router as Router8 } from "express";
|
|
2084
|
-
import { readFileSync as
|
|
2678
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
|
|
2085
2679
|
import { homedir as homedir4 } from "os";
|
|
2086
|
-
import { join as
|
|
2087
|
-
var SUVEREN_DATA_DIR = process.env.SUVEREN_DATA_DIR ??
|
|
2088
|
-
var FILE_PATH =
|
|
2680
|
+
import { join as join7 } from "path";
|
|
2681
|
+
var SUVEREN_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join7(homedir4(), ".suveren");
|
|
2682
|
+
var FILE_PATH = join7(SUVEREN_DATA_DIR, "approved-intents.enc.json");
|
|
2089
2683
|
function readFile() {
|
|
2090
|
-
if (!
|
|
2684
|
+
if (!existsSync7(FILE_PATH)) {
|
|
2091
2685
|
return { version: 1, entries: {} };
|
|
2092
2686
|
}
|
|
2093
2687
|
try {
|
|
2094
|
-
return JSON.parse(
|
|
2688
|
+
return JSON.parse(readFileSync7(FILE_PATH, "utf-8"));
|
|
2095
2689
|
} catch {
|
|
2096
2690
|
return { version: 1, entries: {} };
|
|
2097
2691
|
}
|
|
2098
2692
|
}
|
|
2099
2693
|
function writeFile(data) {
|
|
2100
|
-
|
|
2101
|
-
|
|
2694
|
+
mkdirSync5(SUVEREN_DATA_DIR, { recursive: true });
|
|
2695
|
+
writeFileSync5(FILE_PATH, JSON.stringify(data, null, 2), "utf-8");
|
|
2102
2696
|
}
|
|
2103
2697
|
function readApprovedIntents(vault2) {
|
|
2104
2698
|
const file = readFile();
|
|
@@ -2147,7 +2741,7 @@ function createApprovedIntentsRouter(vault2) {
|
|
|
2147
2741
|
|
|
2148
2742
|
// src/routes/evidence-export.ts
|
|
2149
2743
|
var AS_FETCH_TIMEOUT_MS = 2e4;
|
|
2150
|
-
function createEvidenceExportRouter(spUrl, vault2) {
|
|
2744
|
+
function createEvidenceExportRouter(spUrl, vault2, dataDir, lockAsTlsMismatch2) {
|
|
2151
2745
|
const router = Router9();
|
|
2152
2746
|
const getSpCookie = () => vault2.getSpCookie();
|
|
2153
2747
|
router.get("/", async (_req, res) => {
|
|
@@ -2167,17 +2761,29 @@ function createEvidenceExportRouter(spUrl, vault2) {
|
|
|
2167
2761
|
const controller = new AbortController();
|
|
2168
2762
|
const timeout = setTimeout(() => controller.abort(), AS_FETCH_TIMEOUT_MS);
|
|
2169
2763
|
try {
|
|
2170
|
-
const
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2764
|
+
const pin = readPairing(dataDir);
|
|
2765
|
+
const { res: asRes } = await fetchAs(
|
|
2766
|
+
`${spUrl}/api/receipts/export`,
|
|
2767
|
+
{ headers: { Cookie: cookie }, signal: controller.signal },
|
|
2768
|
+
{
|
|
2769
|
+
enforce: resolvePinTls(dataDir),
|
|
2770
|
+
pinnedSpkiHex: pin && pin.asUrl === spUrl ? pin.tlsSpkiPinHex : void 0
|
|
2771
|
+
// Never capture here — only the sign-in challenge establishes or
|
|
2772
|
+
// refreshes a pin (as-challenge.ts).
|
|
2773
|
+
}
|
|
2774
|
+
);
|
|
2174
2775
|
if (asRes.ok) {
|
|
2175
2776
|
authorityServer = await asRes.json();
|
|
2176
2777
|
} else {
|
|
2177
2778
|
asError = `Authority Server export failed: ${asRes.status}`;
|
|
2178
2779
|
}
|
|
2179
2780
|
} catch (err) {
|
|
2180
|
-
|
|
2781
|
+
if (err instanceof AsTlsMismatchError) {
|
|
2782
|
+
lockAsTlsMismatch2();
|
|
2783
|
+
asError = err.message;
|
|
2784
|
+
} else {
|
|
2785
|
+
asError = `Authority Server unreachable: ${err instanceof Error ? err.message : String(err)}`;
|
|
2786
|
+
}
|
|
2181
2787
|
} finally {
|
|
2182
2788
|
clearTimeout(timeout);
|
|
2183
2789
|
}
|
|
@@ -2363,7 +2969,7 @@ function createDecryptIntentRouter(vault2) {
|
|
|
2363
2969
|
|
|
2364
2970
|
// src/lib/update-checker.ts
|
|
2365
2971
|
import { execSync } from "child_process";
|
|
2366
|
-
import { dirname as
|
|
2972
|
+
import { dirname as dirname5 } from "path";
|
|
2367
2973
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2368
2974
|
var GHCR_IMAGE = "suverenai/suveren-gateway";
|
|
2369
2975
|
var NPM_PACKAGE = "@suveren/gateway";
|
|
@@ -2429,7 +3035,7 @@ function compareSemver(a, b) {
|
|
|
2429
3035
|
return 0;
|
|
2430
3036
|
}
|
|
2431
3037
|
function checkDev() {
|
|
2432
|
-
const cwd =
|
|
3038
|
+
const cwd = dirname5(fileURLToPath2(import.meta.url));
|
|
2433
3039
|
try {
|
|
2434
3040
|
execSync("git fetch origin --quiet", { cwd, stdio: "ignore", timeout: 15e3 });
|
|
2435
3041
|
const out = execSync("git rev-list HEAD..origin/main --count", {
|
|
@@ -2502,19 +3108,19 @@ data: ${data}
|
|
|
2502
3108
|
import { Router as Router12 } from "express";
|
|
2503
3109
|
|
|
2504
3110
|
// src/lib/gateway-settings.ts
|
|
2505
|
-
import { readFileSync as
|
|
3111
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
2506
3112
|
import { homedir as homedir5 } from "os";
|
|
2507
|
-
import { join as
|
|
3113
|
+
import { join as join8, dirname as dirname6 } from "path";
|
|
2508
3114
|
var DEFAULT_SETTINGS = {
|
|
2509
3115
|
desktopNotifications: true
|
|
2510
3116
|
};
|
|
2511
3117
|
function settingsPath(dataDir) {
|
|
2512
|
-
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ??
|
|
2513
|
-
return
|
|
3118
|
+
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join8(homedir5(), ".suveren");
|
|
3119
|
+
return join8(dir, "settings.json");
|
|
2514
3120
|
}
|
|
2515
3121
|
function readSettings(dataDir) {
|
|
2516
3122
|
try {
|
|
2517
|
-
const raw = JSON.parse(
|
|
3123
|
+
const raw = JSON.parse(readFileSync8(settingsPath(dataDir), "utf8"));
|
|
2518
3124
|
return {
|
|
2519
3125
|
desktopNotifications: typeof raw.desktopNotifications === "boolean" ? raw.desktopNotifications : DEFAULT_SETTINGS.desktopNotifications
|
|
2520
3126
|
};
|
|
@@ -2528,8 +3134,8 @@ function writeSettings(patch, dataDir) {
|
|
|
2528
3134
|
...typeof patch.desktopNotifications === "boolean" ? { desktopNotifications: patch.desktopNotifications } : {}
|
|
2529
3135
|
};
|
|
2530
3136
|
const path = settingsPath(dataDir);
|
|
2531
|
-
|
|
2532
|
-
|
|
3137
|
+
mkdirSync6(dirname6(path), { recursive: true });
|
|
3138
|
+
writeFileSync6(path, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
2533
3139
|
return next;
|
|
2534
3140
|
}
|
|
2535
3141
|
|
|
@@ -2561,20 +3167,20 @@ function createGatewaySettingsRouter() {
|
|
|
2561
3167
|
import { Router as Router13 } from "express";
|
|
2562
3168
|
|
|
2563
3169
|
// src/lib/archived-mandates-store.ts
|
|
2564
|
-
import { readFileSync as
|
|
3170
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync } from "fs";
|
|
2565
3171
|
import { homedir as homedir6 } from "os";
|
|
2566
|
-
import { join as
|
|
3172
|
+
import { join as join9, dirname as dirname7 } from "path";
|
|
2567
3173
|
var ID_PATTERN = /^[A-Za-z0-9_.:-]{1,200}$/;
|
|
2568
3174
|
function isValidMandateId(id) {
|
|
2569
3175
|
return typeof id === "string" && ID_PATTERN.test(id);
|
|
2570
3176
|
}
|
|
2571
3177
|
function storePath(dataDir) {
|
|
2572
|
-
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ??
|
|
2573
|
-
return
|
|
3178
|
+
const dir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join9(homedir6(), ".suveren");
|
|
3179
|
+
return join9(dir, "archived-mandates.json");
|
|
2574
3180
|
}
|
|
2575
3181
|
function readArchived(dataDir) {
|
|
2576
3182
|
try {
|
|
2577
|
-
const raw = JSON.parse(
|
|
3183
|
+
const raw = JSON.parse(readFileSync9(storePath(dataDir), "utf8"));
|
|
2578
3184
|
if (!Array.isArray(raw.archived)) return [];
|
|
2579
3185
|
return [...new Set(raw.archived.filter(isValidMandateId))];
|
|
2580
3186
|
} catch {
|
|
@@ -2584,9 +3190,9 @@ function readArchived(dataDir) {
|
|
|
2584
3190
|
function writeArchived(ids, dataDir) {
|
|
2585
3191
|
const next = [...new Set(ids.filter(isValidMandateId))].sort();
|
|
2586
3192
|
const path = storePath(dataDir);
|
|
2587
|
-
|
|
3193
|
+
mkdirSync7(dirname7(path), { recursive: true });
|
|
2588
3194
|
const tmp = `${path}.tmp`;
|
|
2589
|
-
|
|
3195
|
+
writeFileSync7(tmp, JSON.stringify({ archived: next }, null, 2) + "\n", "utf8");
|
|
2590
3196
|
renameSync(tmp, path);
|
|
2591
3197
|
return next;
|
|
2592
3198
|
}
|
|
@@ -2627,6 +3233,8 @@ import { Router as Router14 } from "express";
|
|
|
2627
3233
|
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
2628
3234
|
var ALLOWED = ["proposal-added", "action-approval-needed"];
|
|
2629
3235
|
var SESSION_EXPIRED = "session-expired";
|
|
3236
|
+
var AS_KEY_MISMATCH = "as-key-mismatch";
|
|
3237
|
+
var AS_TLS_MISMATCH = "as-tls-mismatch";
|
|
2630
3238
|
function secretMatches(provided, expected) {
|
|
2631
3239
|
if (!expected) return false;
|
|
2632
3240
|
if (!provided) return false;
|
|
@@ -2635,7 +3243,7 @@ function secretMatches(provided, expected) {
|
|
|
2635
3243
|
if (a.length !== b.length) return false;
|
|
2636
3244
|
return timingSafeEqual2(a, b);
|
|
2637
3245
|
}
|
|
2638
|
-
function createInternalEventsRouter(getSecret, onSessionExpired) {
|
|
3246
|
+
function createInternalEventsRouter(getSecret, onSessionExpired, onAsKeyMismatch, onAsTlsMismatch) {
|
|
2639
3247
|
const router = Router14();
|
|
2640
3248
|
router.post("/event", (req, res) => {
|
|
2641
3249
|
if (!secretMatches(req.headers["x-internal-secret"], getSecret())) {
|
|
@@ -2648,6 +3256,16 @@ function createInternalEventsRouter(getSecret, onSessionExpired) {
|
|
|
2648
3256
|
res.json({ ok: true });
|
|
2649
3257
|
return;
|
|
2650
3258
|
}
|
|
3259
|
+
if (type === AS_KEY_MISMATCH) {
|
|
3260
|
+
onAsKeyMismatch?.();
|
|
3261
|
+
res.json({ ok: true });
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3264
|
+
if (type === AS_TLS_MISMATCH) {
|
|
3265
|
+
onAsTlsMismatch?.();
|
|
3266
|
+
res.json({ ok: true });
|
|
3267
|
+
return;
|
|
3268
|
+
}
|
|
2651
3269
|
if (typeof type !== "string" || !ALLOWED.includes(type)) {
|
|
2652
3270
|
res.status(400).json({ error: "Unsupported event type" });
|
|
2653
3271
|
return;
|
|
@@ -2746,6 +3364,8 @@ function startNotificationDispatcher(opts = {}) {
|
|
|
2746
3364
|
|
|
2747
3365
|
// src/lib/session-lock.ts
|
|
2748
3366
|
var SESSION_LOCKED_MESSAGE = "Your sign-in ended after 30 days or was revoked. Sign in again.";
|
|
3367
|
+
var AS_KEY_MISMATCH_MESSAGE = "The Authority Server presented a signing key that does not match the one pinned at pairing. Sign in again to review.";
|
|
3368
|
+
var AS_TLS_MISMATCH_MESSAGE = "A connection to the Authority Server presented a TLS certificate that does not match the one pinned at pairing. The connection was refused before anything was sent. If the certificate changed intentionally (a new key, not just renewal), clear the pairing and sign in again to re-pin it.";
|
|
2749
3369
|
function createSessionLock(deps) {
|
|
2750
3370
|
const { vault: vault2, port: port2 } = deps;
|
|
2751
3371
|
const notifyFn = deps.notifyFn ?? notify;
|
|
@@ -2763,6 +3383,40 @@ function createSessionLock(deps) {
|
|
|
2763
3383
|
notifyFn(title, message, process.platform, url);
|
|
2764
3384
|
};
|
|
2765
3385
|
}
|
|
3386
|
+
function createAsKeyMismatchLock(deps) {
|
|
3387
|
+
const { vault: vault2, port: port2 } = deps;
|
|
3388
|
+
const notifyFn = deps.notifyFn ?? notify;
|
|
3389
|
+
const unconfigureSessionFn = deps.unconfigureSessionFn ?? unconfigureSession;
|
|
3390
|
+
const emit = deps.emit ?? eventBus.emit.bind(eventBus);
|
|
3391
|
+
return function lockOnAsKeyMismatch() {
|
|
3392
|
+
if (!vault2.isUnlocked()) return;
|
|
3393
|
+
vault2.lockAsKeyMismatch();
|
|
3394
|
+
console.error("[Control Plane] Authority Server key mismatch \u2014 gateway LOCKED");
|
|
3395
|
+
void unconfigureSessionFn("as-key-mismatch").catch((err) => {
|
|
3396
|
+
console.error("[Control Plane] Failed to push cleared session to MCP:", err);
|
|
3397
|
+
});
|
|
3398
|
+
emit("session-locked", { reason: "as-key-mismatch", message: AS_KEY_MISMATCH_MESSAGE });
|
|
3399
|
+
const { title, url } = sessionExpiredNotification(port2);
|
|
3400
|
+
notifyFn(title, AS_KEY_MISMATCH_MESSAGE, process.platform, url);
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3403
|
+
function createAsTlsMismatchLock(deps) {
|
|
3404
|
+
const { vault: vault2, port: port2 } = deps;
|
|
3405
|
+
const notifyFn = deps.notifyFn ?? notify;
|
|
3406
|
+
const unconfigureSessionFn = deps.unconfigureSessionFn ?? unconfigureSession;
|
|
3407
|
+
const emit = deps.emit ?? eventBus.emit.bind(eventBus);
|
|
3408
|
+
return function lockOnAsTlsMismatch() {
|
|
3409
|
+
if (!vault2.isUnlocked()) return;
|
|
3410
|
+
vault2.lockAsTlsMismatch();
|
|
3411
|
+
console.error("[Control Plane] Authority Server TLS pin mismatch \u2014 gateway LOCKED");
|
|
3412
|
+
void unconfigureSessionFn("as-tls-mismatch").catch((err) => {
|
|
3413
|
+
console.error("[Control Plane] Failed to push cleared session to MCP:", err);
|
|
3414
|
+
});
|
|
3415
|
+
emit("session-locked", { reason: "as-tls-mismatch", message: AS_TLS_MISMATCH_MESSAGE });
|
|
3416
|
+
const { title, url } = sessionExpiredNotification(port2);
|
|
3417
|
+
notifyFn(title, AS_TLS_MISMATCH_MESSAGE, process.platform, url);
|
|
3418
|
+
};
|
|
3419
|
+
}
|
|
2766
3420
|
|
|
2767
3421
|
// src/lib/session-expiry-scheduler.ts
|
|
2768
3422
|
var MAX_TIMEOUT_MS = 2147483647;
|
|
@@ -2832,17 +3486,17 @@ function buildSessionHealth(vault2) {
|
|
|
2832
3486
|
}
|
|
2833
3487
|
|
|
2834
3488
|
// src/lib/denials-reader.ts
|
|
2835
|
-
import { existsSync as
|
|
2836
|
-
import { join as
|
|
3489
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10 } from "fs";
|
|
3490
|
+
import { join as join10 } from "path";
|
|
2837
3491
|
function loadDenials(dataDir, decrypt) {
|
|
2838
|
-
const encPath =
|
|
2839
|
-
const plainPath =
|
|
2840
|
-
if (
|
|
2841
|
-
const { blob } = JSON.parse(
|
|
3492
|
+
const encPath = join10(dataDir, "denials.enc.json");
|
|
3493
|
+
const plainPath = join10(dataDir, "denials.json");
|
|
3494
|
+
if (existsSync8(encPath)) {
|
|
3495
|
+
const { blob } = JSON.parse(readFileSync10(encPath, "utf-8"));
|
|
2842
3496
|
return JSON.parse(decrypt(blob)).records ?? [];
|
|
2843
3497
|
}
|
|
2844
|
-
if (
|
|
2845
|
-
return JSON.parse(
|
|
3498
|
+
if (existsSync8(plainPath)) {
|
|
3499
|
+
return JSON.parse(readFileSync10(plainPath, "utf-8")).records ?? [];
|
|
2846
3500
|
}
|
|
2847
3501
|
return [];
|
|
2848
3502
|
}
|
|
@@ -2859,9 +3513,9 @@ function selectDenials(records, opts = {}) {
|
|
|
2859
3513
|
// src/index.ts
|
|
2860
3514
|
(function migrateDataDir() {
|
|
2861
3515
|
if (process.env.SUVEREN_DATA_DIR) return;
|
|
2862
|
-
const oldDir =
|
|
2863
|
-
const newDir =
|
|
2864
|
-
if (!
|
|
3516
|
+
const oldDir = join11(homedir7(), ".hap");
|
|
3517
|
+
const newDir = join11(homedir7(), ".suveren");
|
|
3518
|
+
if (!existsSync9(newDir) && existsSync9(oldDir)) {
|
|
2865
3519
|
try {
|
|
2866
3520
|
renameSync2(oldDir, newDir);
|
|
2867
3521
|
console.error(`[Control Plane] Migrated data directory: ${oldDir} \u2192 ${newDir}`);
|
|
@@ -2871,12 +3525,24 @@ function selectDenials(records, opts = {}) {
|
|
|
2871
3525
|
}
|
|
2872
3526
|
}
|
|
2873
3527
|
})();
|
|
2874
|
-
var
|
|
3528
|
+
var DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join11(homedir7(), ".suveren");
|
|
3529
|
+
var SP_URL = resolveAsUrl(DATA_DIR);
|
|
3530
|
+
validatePinTlsForUrl(resolvePinTls(DATA_DIR), SP_URL);
|
|
2875
3531
|
var port = parseInt(process.env.SUVEREN_CP_PORT ?? "3402", 10);
|
|
2876
3532
|
var HAP_MODE = process.env.HAP_MODE ?? "personal";
|
|
2877
|
-
var UI_DIST = process.env.HAP_UI_DIST ??
|
|
2878
|
-
var vault = new Vault();
|
|
2879
|
-
|
|
3533
|
+
var UI_DIST = process.env.HAP_UI_DIST ?? join11(import.meta.dirname ?? __dirname, "../../ui/dist");
|
|
3534
|
+
var vault = new Vault(DATA_DIR);
|
|
3535
|
+
(function repairIfAsUrlChanged() {
|
|
3536
|
+
const pairing = readPairing(DATA_DIR);
|
|
3537
|
+
if (pairing && pairing.asUrl !== SP_URL) {
|
|
3538
|
+
console.error(
|
|
3539
|
+
`[Control Plane] Authority Server changed (${pairing.asUrl} \u2192 ${SP_URL}) \u2014 clearing the old pairing. Sign in again to re-pair.`
|
|
3540
|
+
);
|
|
3541
|
+
clearPairing(DATA_DIR);
|
|
3542
|
+
vault.markBootLockedAsUrlChanged();
|
|
3543
|
+
}
|
|
3544
|
+
})();
|
|
3545
|
+
var internalSecret2 = process.env.SUVEREN_INTERNAL_SECRET ?? randomBytes3(32).toString("hex");
|
|
2880
3546
|
setInternalSecret(internalSecret2);
|
|
2881
3547
|
var app = express();
|
|
2882
3548
|
var jsonParser = express.json();
|
|
@@ -2899,6 +3565,8 @@ function loginRateLimit(req, res, next) {
|
|
|
2899
3565
|
next();
|
|
2900
3566
|
}
|
|
2901
3567
|
var lockExpiredSession = createSessionLock({ vault, port });
|
|
3568
|
+
var lockAsKeyMismatch = createAsKeyMismatchLock({ vault, port });
|
|
3569
|
+
var lockAsTlsMismatch = createAsTlsMismatchLock({ vault, port });
|
|
2902
3570
|
var sessionExpiryScheduler = new SessionExpiryScheduler(
|
|
2903
3571
|
() => vault.getSessionExpiresAt(),
|
|
2904
3572
|
lockExpiredSession
|
|
@@ -2907,7 +3575,8 @@ app.use("/auth", jsonParser, createAuthRouter(
|
|
|
2907
3575
|
vault,
|
|
2908
3576
|
requireAuth(vault),
|
|
2909
3577
|
loginRateLimit,
|
|
2910
|
-
() => sessionExpiryScheduler.reschedule()
|
|
3578
|
+
() => sessionExpiryScheduler.reschedule(),
|
|
3579
|
+
{ asUrl: SP_URL, dataDir: DATA_DIR }
|
|
2911
3580
|
));
|
|
2912
3581
|
function resolveOrigin(req) {
|
|
2913
3582
|
const fwdHost = req.get("x-forwarded-host");
|
|
@@ -3114,7 +3783,7 @@ app.get("/auth/oauth/:integrationId/health", authGuard, async (req, res) => {
|
|
|
3114
3783
|
}
|
|
3115
3784
|
});
|
|
3116
3785
|
app.get("/events", requireAllowedHost, requireAuthQueryOrHeader(vault), createEventsHandler());
|
|
3117
|
-
app.use("/internal", jsonParser, createInternalEventsRouter(() => internalSecret2, lockExpiredSession));
|
|
3786
|
+
app.use("/internal", jsonParser, createInternalEventsRouter(() => internalSecret2, lockExpiredSession, lockAsKeyMismatch, lockAsTlsMismatch));
|
|
3118
3787
|
app.use("/vault", jsonParser, authGuard, createVaultRouter(vault));
|
|
3119
3788
|
app.use("/ai", jsonParser, authGuard, createAIRouter(vault));
|
|
3120
3789
|
app.use("/ai-prompts", jsonParser, authGuard, createAIPromptsRouter());
|
|
@@ -3123,7 +3792,7 @@ app.use("/autostart", jsonParser, authGuard, createAutostartRouter());
|
|
|
3123
3792
|
app.use("/api/gateway-settings", jsonParser, authGuard, createGatewaySettingsRouter());
|
|
3124
3793
|
app.use("/api/archived-mandates", jsonParser, authGuard, createArchivedMandatesRouter());
|
|
3125
3794
|
app.use("/api/encrypt-intent", jsonParser, authGuard, createEncryptIntentRouter());
|
|
3126
|
-
app.use("/api/evidence-export", authGuard, createEvidenceExportRouter(
|
|
3795
|
+
app.use("/api/evidence-export", authGuard, createEvidenceExportRouter(SP_URL, vault, DATA_DIR, lockAsTlsMismatch));
|
|
3127
3796
|
app.use("/api/evidence", authGuard, createEvidenceRouter());
|
|
3128
3797
|
app.use("/api/decrypt-intent", jsonParser, authGuard, createDecryptIntentRouter(vault));
|
|
3129
3798
|
app.use("/api/approved-intents", jsonParser, authGuard, createApprovedIntentsRouter(vault));
|
|
@@ -3253,9 +3922,34 @@ app.get("/active-authorizations", authGuard, async (_req, res) => {
|
|
|
3253
3922
|
res.status(500).json({ error: "Failed to fetch authorizations from MCP server" });
|
|
3254
3923
|
}
|
|
3255
3924
|
});
|
|
3925
|
+
app.get("/skipped-commitments", authGuard, async (_req, res) => {
|
|
3926
|
+
try {
|
|
3927
|
+
const data = await getSkippedCommitments();
|
|
3928
|
+
res.json(data);
|
|
3929
|
+
} catch (err) {
|
|
3930
|
+
console.error("[Control Plane] Skipped-commitments retrieval error:", err);
|
|
3931
|
+
res.status(500).json({ error: "Failed to fetch skipped commitments from MCP server" });
|
|
3932
|
+
}
|
|
3933
|
+
});
|
|
3934
|
+
app.get("/as-pairing", authGuard, (_req, res) => {
|
|
3935
|
+
const pairing = readPairing(DATA_DIR);
|
|
3936
|
+
const paired = pairing !== null && pairing.asUrl === SP_URL;
|
|
3937
|
+
res.json({
|
|
3938
|
+
asUrl: SP_URL,
|
|
3939
|
+
paired,
|
|
3940
|
+
fingerprint: paired ? fingerprintOf(pairing.publicKeyHex) : null,
|
|
3941
|
+
pairedAt: paired ? pairing.pairedAt : null,
|
|
3942
|
+
// Opt-in TLS pinning (`config set pin-tls on`) — see as-tls-pin.ts.
|
|
3943
|
+
// `tlsPinFingerprint` uses the SAME display convention as the signing
|
|
3944
|
+
// key (formatPinFingerprint mirrors fingerprintOf's grouping), applied
|
|
3945
|
+
// to the already-computed SPKI digest rather than re-hashing a key.
|
|
3946
|
+
pinTlsEnabled: resolvePinTls(DATA_DIR),
|
|
3947
|
+
tlsPinFingerprint: paired && pairing.tlsSpkiPinHex ? formatPinFingerprint(pairing.tlsSpkiPinHex) : null
|
|
3948
|
+
});
|
|
3949
|
+
});
|
|
3256
3950
|
app.get("/denials", authGuard, (req, res) => {
|
|
3257
3951
|
try {
|
|
3258
|
-
const dataDir = process.env.SUVEREN_DATA_DIR ??
|
|
3952
|
+
const dataDir = process.env.SUVEREN_DATA_DIR ?? join11(homedir7(), ".suveren");
|
|
3259
3953
|
const all = loadDenials(dataDir, (blob) => vault.decrypt(blob));
|
|
3260
3954
|
const since = Number(req.query.since);
|
|
3261
3955
|
const limit = Number(req.query.limit);
|
|
@@ -3306,11 +4000,11 @@ app.put("/agent-brief/context", jsonParser, authGuard, async (req, res) => {
|
|
|
3306
4000
|
res.status(413).json({ error: `Context exceeds ${AGENT_CONTEXT_MAX_BYTES}-byte cap` });
|
|
3307
4001
|
return;
|
|
3308
4002
|
}
|
|
3309
|
-
const { mkdirSync:
|
|
4003
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync8, renameSync: renameSync3 } = await import("fs");
|
|
3310
4004
|
const filePath = agentBriefPath();
|
|
3311
|
-
|
|
4005
|
+
mkdirSync8(dirname8(filePath), { recursive: true });
|
|
3312
4006
|
const tmpPath = `${filePath}.tmp`;
|
|
3313
|
-
|
|
4007
|
+
writeFileSync8(tmpPath, content, "utf-8");
|
|
3314
4008
|
renameSync3(tmpPath, filePath);
|
|
3315
4009
|
res.json({ ok: true });
|
|
3316
4010
|
} catch (err) {
|
|
@@ -3319,11 +4013,19 @@ app.put("/agent-brief/context", jsonParser, authGuard, async (req, res) => {
|
|
|
3319
4013
|
}
|
|
3320
4014
|
});
|
|
3321
4015
|
app.use("/api", authGuard);
|
|
4016
|
+
var pinnedProxyAgent = SP_URL.startsWith("https:") ? buildPinnedHttpsAgent(() => {
|
|
4017
|
+
const pin = readPairing(DATA_DIR);
|
|
4018
|
+
return {
|
|
4019
|
+
enforce: resolvePinTls(DATA_DIR),
|
|
4020
|
+
pinnedSpkiHex: pin && pin.asUrl === SP_URL ? pin.tlsSpkiPinHex : void 0
|
|
4021
|
+
};
|
|
4022
|
+
}) : void 0;
|
|
3322
4023
|
app.use(
|
|
3323
4024
|
createProxyMiddleware({
|
|
3324
|
-
target:
|
|
4025
|
+
target: SP_URL,
|
|
3325
4026
|
changeOrigin: true,
|
|
3326
4027
|
pathFilter: "/api",
|
|
4028
|
+
...pinnedProxyAgent ? { agent: pinnedProxyAgent } : {},
|
|
3327
4029
|
on: {
|
|
3328
4030
|
proxyReq: (proxyReq) => {
|
|
3329
4031
|
const cookie = vault.getSpCookie();
|
|
@@ -3331,6 +4033,21 @@ app.use(
|
|
|
3331
4033
|
proxyReq.setHeader("Cookie", cookie);
|
|
3332
4034
|
}
|
|
3333
4035
|
},
|
|
4036
|
+
// A pin check failure means the connection never completed its TLS
|
|
4037
|
+
// handshake — nothing (not even this call's own cookie) reached the
|
|
4038
|
+
// network. Lock the gateway with the real reason, loudly; an ordinary
|
|
4039
|
+
// network error (AS outage) is NOT a pin failure (see isPinCheckError
|
|
4040
|
+
// / as-tls-pin.ts's module doc comment on outage misclassification)
|
|
4041
|
+
// and falls through to http-proxy-middleware's default error handling.
|
|
4042
|
+
error: (err, _req, res) => {
|
|
4043
|
+
if (!isPinCheckError(err)) return;
|
|
4044
|
+
console.error("[Control Plane] /api proxy: TLS pin mismatch \u2014 gateway LOCKED:", err.message);
|
|
4045
|
+
lockAsTlsMismatch();
|
|
4046
|
+
if (res && "writeHead" in res && !res.headersSent) {
|
|
4047
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
4048
|
+
res.end(JSON.stringify({ error: "as_tls_mismatch", message: err.message }));
|
|
4049
|
+
}
|
|
4050
|
+
},
|
|
3334
4051
|
proxyRes: (proxyRes, req) => {
|
|
3335
4052
|
const status = proxyRes.statusCode ?? 0;
|
|
3336
4053
|
if (status === 401 && vault.isUnlocked()) {
|
|
@@ -3363,13 +4080,13 @@ app.use(
|
|
|
3363
4080
|
})
|
|
3364
4081
|
);
|
|
3365
4082
|
function detectInstallMethod() {
|
|
3366
|
-
if (
|
|
4083
|
+
if (existsSync9("/.dockerenv")) return "docker";
|
|
3367
4084
|
const dir = import.meta.dirname ?? __dirname;
|
|
3368
4085
|
if (dir.includes("/node_modules/@suveren/gateway/")) return "npm";
|
|
3369
4086
|
let cursor = dir;
|
|
3370
4087
|
for (let i = 0; i < 8; i++) {
|
|
3371
|
-
if (
|
|
3372
|
-
const parent =
|
|
4088
|
+
if (existsSync9(join11(cursor, ".git"))) return "dev";
|
|
4089
|
+
const parent = dirname8(cursor);
|
|
3373
4090
|
if (parent === cursor) break;
|
|
3374
4091
|
cursor = parent;
|
|
3375
4092
|
}
|
|
@@ -3381,10 +4098,10 @@ function detectRunningVersion() {
|
|
|
3381
4098
|
return process.env.HAP_BUILD_SHA ?? "dev";
|
|
3382
4099
|
}
|
|
3383
4100
|
const dir = import.meta.dirname ?? __dirname;
|
|
3384
|
-
const bundlePkg =
|
|
3385
|
-
if (
|
|
4101
|
+
const bundlePkg = join11(dir, "..", "..", "package.json");
|
|
4102
|
+
if (existsSync9(bundlePkg)) {
|
|
3386
4103
|
try {
|
|
3387
|
-
const pkg = JSON.parse(
|
|
4104
|
+
const pkg = JSON.parse(readFileSync11(bundlePkg, "utf8"));
|
|
3388
4105
|
if (pkg.name === "@suveren/gateway" && typeof pkg.version === "string") {
|
|
3389
4106
|
return pkg.version;
|
|
3390
4107
|
}
|
|
@@ -3406,14 +4123,14 @@ app.get("/health", async (req, res) => {
|
|
|
3406
4123
|
latestVersion: update.latestVersion,
|
|
3407
4124
|
updateAvailable: update.updateAvailable,
|
|
3408
4125
|
installMethod: INSTALL_METHOD,
|
|
3409
|
-
spUrl:
|
|
4126
|
+
spUrl: SP_URL,
|
|
3410
4127
|
session: buildSessionHealth(vault),
|
|
3411
4128
|
security: {
|
|
3412
4129
|
note: "Gateway secures tool execution. Agent host isolation is the user's responsibility."
|
|
3413
4130
|
}
|
|
3414
4131
|
});
|
|
3415
4132
|
});
|
|
3416
|
-
if (
|
|
4133
|
+
if (existsSync9(UI_DIST)) {
|
|
3417
4134
|
app.use(express.static(UI_DIST, {
|
|
3418
4135
|
setHeaders: (res, filePath) => {
|
|
3419
4136
|
if (filePath.endsWith("index.html")) {
|
|
@@ -3423,7 +4140,7 @@ if (existsSync7(UI_DIST)) {
|
|
|
3423
4140
|
}));
|
|
3424
4141
|
app.get("*", (_req, res) => {
|
|
3425
4142
|
res.setHeader("Cache-Control", "no-store, must-revalidate");
|
|
3426
|
-
res.sendFile(
|
|
4143
|
+
res.sendFile(join11(UI_DIST, "index.html"));
|
|
3427
4144
|
});
|
|
3428
4145
|
} else {
|
|
3429
4146
|
app.get("/", (_req, res) => {
|
|
@@ -3441,7 +4158,7 @@ app.listen(port, "0.0.0.0", () => {
|
|
|
3441
4158
|
}
|
|
3442
4159
|
startNotificationDispatcher({ url: `http://localhost:${port}` });
|
|
3443
4160
|
sessionExpiryScheduler.start();
|
|
3444
|
-
console.error(`[Control Plane] SP proxy: ${
|
|
4161
|
+
console.error(`[Control Plane] SP proxy: ${SP_URL}`);
|
|
3445
4162
|
console.error(`[Control Plane] UI dist: ${UI_DIST}`);
|
|
3446
4163
|
console.error(`[Control Plane] Internal secret: configured`);
|
|
3447
4164
|
console.error(`[Control Plane] MCP server: ${MCP_BASE}`);
|