@suveren/gateway 0.8.7 → 0.9.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/bin/suveren-gateway.js +165 -9
- package/dist/control-plane/index.mjs +330 -87
- package/dist/mcp-server/http.mjs +662 -186
- package/dist/ui/assets/{index-tzStUGuj.js → index-CIiOCgjJ.js} +21 -21
- package/dist/ui/index.html +1 -1
- package/lib/config.d.mts +37 -0
- package/lib/config.mjs +150 -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/package.json +2 -2
- 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
package/dist/mcp-server/http.mjs
CHANGED
|
@@ -155,12 +155,19 @@ var SPClient = class {
|
|
|
155
155
|
}
|
|
156
156
|
/**
|
|
157
157
|
* Drop the session because the control plane learned (by whatever path —
|
|
158
|
-
* one of OUR calls 401ing,
|
|
159
|
-
* Idempotent: safe to call redundantly from the
|
|
158
|
+
* one of OUR calls 401ing, its own AS proxy 401ing, or an AS key mismatch)
|
|
159
|
+
* that it ended. Idempotent: safe to call redundantly from the
|
|
160
|
+
* control-plane's push.
|
|
161
|
+
*
|
|
162
|
+
* @param reason Defaults to 'expired' for the original caller (a 401 really
|
|
163
|
+
* does mean the session ended) — but the control plane's own lock
|
|
164
|
+
* procedures (session-lock.ts) know the REAL reason and must pass it, or
|
|
165
|
+
* an agent told "your sign-in ended, sign in again" for an AS key
|
|
166
|
+
* mismatch would be sent to a sign-in that is itself refused.
|
|
160
167
|
*/
|
|
161
|
-
clearSession() {
|
|
168
|
+
clearSession(reason = "expired") {
|
|
162
169
|
this.sessionCookie = "";
|
|
163
|
-
this.lockReason =
|
|
170
|
+
this.lockReason = reason;
|
|
164
171
|
}
|
|
165
172
|
/** Why we are currently locked, if known. `null` means the default
|
|
166
173
|
* boot-locked case (nobody has signed in yet this run). */
|
|
@@ -364,13 +371,52 @@ var SPClient = class {
|
|
|
364
371
|
|
|
365
372
|
// src/lib/attestation-cache.ts
|
|
366
373
|
import { decodeAttestationBlob } from "@hap/core";
|
|
374
|
+
|
|
375
|
+
// src/lib/as-pairing.ts
|
|
376
|
+
import { createHash } from "crypto";
|
|
377
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
|
|
378
|
+
import { dirname, join as join2 } from "path";
|
|
379
|
+
function pairingPath(dataDir2) {
|
|
380
|
+
return join2(dataDir2, "as-pairing.json");
|
|
381
|
+
}
|
|
382
|
+
function readPairing(dataDir2) {
|
|
383
|
+
const path = pairingPath(dataDir2);
|
|
384
|
+
if (!existsSync2(path)) return null;
|
|
385
|
+
try {
|
|
386
|
+
const data = JSON.parse(readFileSync2(path, "utf-8"));
|
|
387
|
+
if (typeof data.asUrl !== "string" || typeof data.publicKeyHex !== "string") return null;
|
|
388
|
+
return { asUrl: data.asUrl, publicKeyHex: data.publicKeyHex, pairedAt: data.pairedAt ?? "" };
|
|
389
|
+
} catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function fingerprintOf(publicKeyHex) {
|
|
394
|
+
const raw = Buffer.from(publicKeyHex, "hex");
|
|
395
|
+
const digest = createHash("sha256").update(raw).digest("hex").toUpperCase();
|
|
396
|
+
return digest.match(/.{1,4}/g)?.join(":") ?? digest;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/lib/attestation-cache.ts
|
|
400
|
+
var AsKeyMismatchError = class extends Error {
|
|
401
|
+
constructor(message) {
|
|
402
|
+
super(message);
|
|
403
|
+
this.name = "AsKeyMismatchError";
|
|
404
|
+
}
|
|
405
|
+
};
|
|
367
406
|
function isCommitmentDowngrade(auth) {
|
|
368
407
|
const requiresReview = auth.signedCommitmentMode === "review" || auth.signedCommitmentMode === "review_above_cap";
|
|
369
408
|
return requiresReview && (auth.deferredCommitmentDomains ?? []).length === 0;
|
|
370
409
|
}
|
|
371
410
|
var AttestationCache = class {
|
|
372
|
-
|
|
411
|
+
/**
|
|
412
|
+
* @param dataDir Where to look for a pinned key (as-pairing.json). Optional
|
|
413
|
+
* and defaults to "no pin enforced" — kept optional so existing
|
|
414
|
+
* constructions (and this class's own unit tests) that pass only an
|
|
415
|
+
* SPClient keep working unpinned, exactly as before pinning existed.
|
|
416
|
+
*/
|
|
417
|
+
constructor(spClient, dataDir2) {
|
|
373
418
|
this.spClient = spClient;
|
|
419
|
+
this.dataDir = dataDir2;
|
|
374
420
|
}
|
|
375
421
|
spPublicKey = null;
|
|
376
422
|
spPublicKeyFetchedAt = 0;
|
|
@@ -380,15 +426,29 @@ var AttestationCache = class {
|
|
|
380
426
|
authorizations = /* @__PURE__ */ new Map();
|
|
381
427
|
lastSync = 0;
|
|
382
428
|
/**
|
|
383
|
-
* Get the SP public key, fetching from SP if not cached or expired
|
|
429
|
+
* Get the SP public key, fetching from SP if not cached or expired, then —
|
|
430
|
+
* when a pin exists for this exact AS URL — verifying the live key still
|
|
431
|
+
* matches it.
|
|
432
|
+
*
|
|
433
|
+
* Trust-on-first-use before any pairing exists (or when no `dataDir` was
|
|
434
|
+
* given): the fetched key is cached and returned, same as before pinning.
|
|
435
|
+
* Once paired, a live key that differs from the pin throws
|
|
436
|
+
* {@link AsKeyMismatchError} — fail closed, never silently re-pin.
|
|
384
437
|
*/
|
|
385
438
|
async getPublicKey() {
|
|
386
439
|
const now = Math.floor(Date.now() / 1e3);
|
|
387
|
-
if (this.spPublicKey && now - this.spPublicKeyFetchedAt < this.SP_PUBKEY_TTL) {
|
|
388
|
-
|
|
440
|
+
if (!(this.spPublicKey && now - this.spPublicKeyFetchedAt < this.SP_PUBKEY_TTL)) {
|
|
441
|
+
this.spPublicKey = await this.spClient.getPublicKey();
|
|
442
|
+
this.spPublicKeyFetchedAt = now;
|
|
443
|
+
}
|
|
444
|
+
if (this.dataDir) {
|
|
445
|
+
const pin = readPairing(this.dataDir);
|
|
446
|
+
if (pin && pin.asUrl === this.spClient.url && pin.publicKeyHex !== this.spPublicKey) {
|
|
447
|
+
throw new AsKeyMismatchError(
|
|
448
|
+
`The Authority Server at ${this.spClient.url} presented a signing key that does not match the one pinned at pairing (pinned fingerprint ${fingerprintOf(pin.publicKeyHex)}). Refusing to trust it. Re-pair (sign in again) only if you expect this key to have changed.`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
389
451
|
}
|
|
390
|
-
this.spPublicKey = await this.spClient.getPublicKey();
|
|
391
|
-
this.spPublicKeyFetchedAt = now;
|
|
392
452
|
return this.spPublicKey;
|
|
393
453
|
}
|
|
394
454
|
/**
|
|
@@ -498,18 +558,18 @@ var AttestationCache = class {
|
|
|
498
558
|
};
|
|
499
559
|
|
|
500
560
|
// src/lib/gate-store.ts
|
|
501
|
-
import { mkdirSync, readFileSync as
|
|
561
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
502
562
|
import { homedir } from "os";
|
|
503
|
-
import { dirname, join as
|
|
563
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
504
564
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
505
|
-
var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ??
|
|
565
|
+
var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ?? join3(homedir(), ".suveren");
|
|
506
566
|
var GateStore = class {
|
|
507
567
|
entries = /* @__PURE__ */ new Map();
|
|
508
568
|
baseDir;
|
|
509
569
|
vaultKey = null;
|
|
510
570
|
constructor(filePath) {
|
|
511
571
|
if (filePath && filePath.endsWith(".json")) {
|
|
512
|
-
this.baseDir =
|
|
572
|
+
this.baseDir = dirname2(filePath);
|
|
513
573
|
} else {
|
|
514
574
|
this.baseDir = filePath ?? DEFAULT_DIR;
|
|
515
575
|
}
|
|
@@ -520,13 +580,13 @@ var GateStore = class {
|
|
|
520
580
|
*/
|
|
521
581
|
setVaultKey(key) {
|
|
522
582
|
this.vaultKey = key;
|
|
523
|
-
if (
|
|
583
|
+
if (existsSync3(this.encryptedFilePath)) {
|
|
524
584
|
this.loadEncrypted();
|
|
525
585
|
} else if (this.entries.size > 0) {
|
|
526
586
|
this.persistEncrypted();
|
|
527
|
-
if (
|
|
587
|
+
if (existsSync3(this.plaintextFilePath)) {
|
|
528
588
|
try {
|
|
529
|
-
|
|
589
|
+
unlinkSync2(this.plaintextFilePath);
|
|
530
590
|
} catch {
|
|
531
591
|
}
|
|
532
592
|
}
|
|
@@ -546,6 +606,30 @@ var GateStore = class {
|
|
|
546
606
|
this.entries.delete(path);
|
|
547
607
|
this.persist();
|
|
548
608
|
}
|
|
609
|
+
/**
|
|
610
|
+
* Wipe every locally cached gate. Used when the Authority Server this
|
|
611
|
+
* gateway points at changes (re-pairing, see as-pairing.ts): a stored
|
|
612
|
+
* authorization id and its intent/context are meaningless against a
|
|
613
|
+
* different AS's grants, and keeping them around risks a `getAll()` caller
|
|
614
|
+
* (e.g. list-authorizations) advertising authority that no longer exists.
|
|
615
|
+
*
|
|
616
|
+
* Removes BOTH the plaintext and encrypted files, not just the one
|
|
617
|
+
* currently active — this runs at boot, before any vault key is set, so
|
|
618
|
+
* `persist()` would otherwise only touch `gates.json` and leave a stale
|
|
619
|
+
* `gates.enc.json` in place for `setVaultKey()` to resurrect on the next
|
|
620
|
+
* unlock.
|
|
621
|
+
*/
|
|
622
|
+
clearAll() {
|
|
623
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
624
|
+
try {
|
|
625
|
+
if (existsSync3(this.plaintextFilePath)) unlinkSync2(this.plaintextFilePath);
|
|
626
|
+
} catch {
|
|
627
|
+
}
|
|
628
|
+
try {
|
|
629
|
+
if (existsSync3(this.encryptedFilePath)) unlinkSync2(this.encryptedFilePath);
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
}
|
|
549
633
|
// ─── Encryption helpers ─────────────────────────────────────────────────
|
|
550
634
|
encrypt(plaintext) {
|
|
551
635
|
if (!this.vaultKey) throw new Error("No vault key");
|
|
@@ -575,19 +659,19 @@ var GateStore = class {
|
|
|
575
659
|
}
|
|
576
660
|
// ─── File paths ─────────────────────────────────────────────────────────
|
|
577
661
|
get plaintextFilePath() {
|
|
578
|
-
return
|
|
662
|
+
return join3(this.baseDir, "gates.json");
|
|
579
663
|
}
|
|
580
664
|
get encryptedFilePath() {
|
|
581
|
-
return
|
|
665
|
+
return join3(this.baseDir, "gates.enc.json");
|
|
582
666
|
}
|
|
583
667
|
// ─── Load / Persist ─────────────────────────────────────────────────────
|
|
584
668
|
loadPlaintext() {
|
|
585
|
-
if (!
|
|
586
|
-
|
|
669
|
+
if (!existsSync3(this.plaintextFilePath)) {
|
|
670
|
+
mkdirSync2(this.baseDir, { recursive: true });
|
|
587
671
|
return;
|
|
588
672
|
}
|
|
589
673
|
try {
|
|
590
|
-
const raw =
|
|
674
|
+
const raw = readFileSync3(this.plaintextFilePath, "utf-8");
|
|
591
675
|
const data = JSON.parse(raw);
|
|
592
676
|
this.entries = new Map(Object.entries(data.entries));
|
|
593
677
|
} catch {
|
|
@@ -596,9 +680,9 @@ var GateStore = class {
|
|
|
596
680
|
}
|
|
597
681
|
}
|
|
598
682
|
loadEncrypted() {
|
|
599
|
-
if (!
|
|
683
|
+
if (!existsSync3(this.encryptedFilePath)) return;
|
|
600
684
|
try {
|
|
601
|
-
const raw =
|
|
685
|
+
const raw = readFileSync3(this.encryptedFilePath, "utf-8");
|
|
602
686
|
const data = JSON.parse(raw);
|
|
603
687
|
this.entries = /* @__PURE__ */ new Map();
|
|
604
688
|
for (const [key, blob] of Object.entries(data.entries)) {
|
|
@@ -622,8 +706,8 @@ var GateStore = class {
|
|
|
622
706
|
version: 1,
|
|
623
707
|
entries: Object.fromEntries(this.entries)
|
|
624
708
|
};
|
|
625
|
-
|
|
626
|
-
|
|
709
|
+
mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
|
|
710
|
+
writeFileSync2(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
627
711
|
}
|
|
628
712
|
persistEncrypted() {
|
|
629
713
|
const data = {
|
|
@@ -633,17 +717,17 @@ var GateStore = class {
|
|
|
633
717
|
for (const [key, entry] of this.entries) {
|
|
634
718
|
data.entries[key] = this.encrypt(JSON.stringify(entry));
|
|
635
719
|
}
|
|
636
|
-
|
|
637
|
-
|
|
720
|
+
mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
|
|
721
|
+
writeFileSync2(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
638
722
|
}
|
|
639
723
|
};
|
|
640
724
|
|
|
641
725
|
// src/lib/execution-log.ts
|
|
642
|
-
import { mkdirSync as
|
|
726
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
643
727
|
import { homedir as homedir2 } from "os";
|
|
644
|
-
import { dirname as
|
|
728
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
645
729
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
|
|
646
|
-
var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ??
|
|
730
|
+
var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ?? join4(homedir2(), ".suveren");
|
|
647
731
|
var MAX_AGE_SECONDS = 31 * 24 * 60 * 60;
|
|
648
732
|
var ExecutionLog = class {
|
|
649
733
|
entries = [];
|
|
@@ -651,7 +735,7 @@ var ExecutionLog = class {
|
|
|
651
735
|
vaultKey = null;
|
|
652
736
|
constructor(filePath) {
|
|
653
737
|
if (filePath && filePath.endsWith(".json")) {
|
|
654
|
-
this.baseDir =
|
|
738
|
+
this.baseDir = dirname3(filePath);
|
|
655
739
|
} else {
|
|
656
740
|
this.baseDir = filePath ?? DEFAULT_DIR2;
|
|
657
741
|
}
|
|
@@ -662,13 +746,13 @@ var ExecutionLog = class {
|
|
|
662
746
|
*/
|
|
663
747
|
setVaultKey(key) {
|
|
664
748
|
this.vaultKey = key;
|
|
665
|
-
if (
|
|
749
|
+
if (existsSync4(this.encryptedFilePath)) {
|
|
666
750
|
this.loadEncrypted();
|
|
667
751
|
} else if (this.entries.length > 0) {
|
|
668
752
|
this.persistEncrypted();
|
|
669
|
-
if (
|
|
753
|
+
if (existsSync4(this.plaintextFilePath)) {
|
|
670
754
|
try {
|
|
671
|
-
|
|
755
|
+
unlinkSync3(this.plaintextFilePath);
|
|
672
756
|
} catch {
|
|
673
757
|
}
|
|
674
758
|
}
|
|
@@ -690,14 +774,23 @@ var ExecutionLog = class {
|
|
|
690
774
|
* @param field - The execution field to sum ("_count" for plain counting)
|
|
691
775
|
* @param window - Time window (daily, weekly, monthly)
|
|
692
776
|
* @param now - Current timestamp in seconds (for testing)
|
|
777
|
+
* @param actionTypes - Only count entries whose `execution.action_type` is one
|
|
778
|
+
* of these (omitted → all). Consumption is partitioned by action type, as at
|
|
779
|
+
* the Authority Server: without it, the usage shown for sales' "orders per
|
|
780
|
+
* day" counted every quote and send. An entry with no action_type counts against every filter —
|
|
781
|
+
* an unknown action is not evidence of headroom.
|
|
693
782
|
*/
|
|
694
|
-
sumByWindow(profileId, path, field, window, now = Math.floor(Date.now() / 1e3)) {
|
|
783
|
+
sumByWindow(profileId, path, field, window, now = Math.floor(Date.now() / 1e3), actionTypes) {
|
|
695
784
|
const cutoff = windowCutoff(window, now);
|
|
696
785
|
let total = 0;
|
|
697
786
|
for (const entry of this.entries) {
|
|
698
787
|
if (entry.profileId !== profileId) continue;
|
|
699
788
|
if (entry.path !== path) continue;
|
|
700
789
|
if (entry.timestamp < cutoff) continue;
|
|
790
|
+
if (actionTypes) {
|
|
791
|
+
const at = entry.execution.action_type;
|
|
792
|
+
if (typeof at === "string" && !actionTypes.includes(at)) continue;
|
|
793
|
+
}
|
|
701
794
|
if (field === "_count") {
|
|
702
795
|
total += 1;
|
|
703
796
|
} else {
|
|
@@ -761,19 +854,19 @@ var ExecutionLog = class {
|
|
|
761
854
|
}
|
|
762
855
|
// ─── File paths ─────────────────────────────────────────────────────────
|
|
763
856
|
get plaintextFilePath() {
|
|
764
|
-
return
|
|
857
|
+
return join4(this.baseDir, "execution-log.json");
|
|
765
858
|
}
|
|
766
859
|
get encryptedFilePath() {
|
|
767
|
-
return
|
|
860
|
+
return join4(this.baseDir, "execution-log.enc.json");
|
|
768
861
|
}
|
|
769
862
|
// ─── Load / Persist ─────────────────────────────────────────────────────
|
|
770
863
|
loadPlaintext() {
|
|
771
|
-
if (!
|
|
772
|
-
|
|
864
|
+
if (!existsSync4(this.plaintextFilePath)) {
|
|
865
|
+
mkdirSync3(this.baseDir, { recursive: true });
|
|
773
866
|
return;
|
|
774
867
|
}
|
|
775
868
|
try {
|
|
776
|
-
const raw =
|
|
869
|
+
const raw = readFileSync4(this.plaintextFilePath, "utf-8");
|
|
777
870
|
const data = JSON.parse(raw);
|
|
778
871
|
this.entries = data.entries;
|
|
779
872
|
this.prune();
|
|
@@ -783,9 +876,9 @@ var ExecutionLog = class {
|
|
|
783
876
|
}
|
|
784
877
|
}
|
|
785
878
|
loadEncrypted() {
|
|
786
|
-
if (!
|
|
879
|
+
if (!existsSync4(this.encryptedFilePath)) return;
|
|
787
880
|
try {
|
|
788
|
-
const raw =
|
|
881
|
+
const raw = readFileSync4(this.encryptedFilePath, "utf-8");
|
|
789
882
|
const data = JSON.parse(raw);
|
|
790
883
|
const decrypted = this.decrypt(data.blob);
|
|
791
884
|
const logFile = JSON.parse(decrypted);
|
|
@@ -805,8 +898,8 @@ var ExecutionLog = class {
|
|
|
805
898
|
}
|
|
806
899
|
persistPlaintext() {
|
|
807
900
|
const data = { version: 1, entries: this.entries };
|
|
808
|
-
|
|
809
|
-
|
|
901
|
+
mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
|
|
902
|
+
writeFileSync3(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
810
903
|
}
|
|
811
904
|
persistEncrypted() {
|
|
812
905
|
const logFile = { version: 1, entries: this.entries };
|
|
@@ -814,8 +907,8 @@ var ExecutionLog = class {
|
|
|
814
907
|
version: 1,
|
|
815
908
|
blob: this.encrypt(JSON.stringify(logFile))
|
|
816
909
|
};
|
|
817
|
-
|
|
818
|
-
|
|
910
|
+
mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
|
|
911
|
+
writeFileSync3(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
819
912
|
}
|
|
820
913
|
};
|
|
821
914
|
function windowCutoff(window, now) {
|
|
@@ -832,11 +925,11 @@ function windowCutoff(window, now) {
|
|
|
832
925
|
}
|
|
833
926
|
|
|
834
927
|
// src/lib/denial-log.ts
|
|
835
|
-
import { mkdirSync as
|
|
928
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, unlinkSync as unlinkSync4 } from "fs";
|
|
836
929
|
import { homedir as homedir3 } from "os";
|
|
837
|
-
import { dirname as
|
|
930
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
838
931
|
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes3 } from "crypto";
|
|
839
|
-
var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ??
|
|
932
|
+
var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ?? join5(homedir3(), ".suveren");
|
|
840
933
|
var MAX_RECORDS = 200;
|
|
841
934
|
var MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
842
935
|
var DenialLog = class {
|
|
@@ -844,18 +937,18 @@ var DenialLog = class {
|
|
|
844
937
|
baseDir;
|
|
845
938
|
vaultKey = null;
|
|
846
939
|
constructor(filePath) {
|
|
847
|
-
this.baseDir = filePath && filePath.endsWith(".json") ?
|
|
940
|
+
this.baseDir = filePath && filePath.endsWith(".json") ? dirname4(filePath) : filePath ?? DEFAULT_DIR3;
|
|
848
941
|
this.loadPlaintext();
|
|
849
942
|
}
|
|
850
943
|
setVaultKey(key) {
|
|
851
944
|
this.vaultKey = key;
|
|
852
|
-
if (
|
|
945
|
+
if (existsSync5(this.encryptedFilePath)) {
|
|
853
946
|
this.loadEncrypted();
|
|
854
947
|
} else if (this.records.length > 0) {
|
|
855
948
|
this.persistEncrypted();
|
|
856
|
-
if (
|
|
949
|
+
if (existsSync5(this.plaintextFilePath)) {
|
|
857
950
|
try {
|
|
858
|
-
|
|
951
|
+
unlinkSync4(this.plaintextFilePath);
|
|
859
952
|
} catch {
|
|
860
953
|
}
|
|
861
954
|
}
|
|
@@ -903,18 +996,18 @@ var DenialLog = class {
|
|
|
903
996
|
return Buffer.concat([decipher.update(Buffer.from(blob.ciphertext, "hex")), decipher.final()]).toString("utf8");
|
|
904
997
|
}
|
|
905
998
|
get plaintextFilePath() {
|
|
906
|
-
return
|
|
999
|
+
return join5(this.baseDir, "denials.json");
|
|
907
1000
|
}
|
|
908
1001
|
get encryptedFilePath() {
|
|
909
|
-
return
|
|
1002
|
+
return join5(this.baseDir, "denials.enc.json");
|
|
910
1003
|
}
|
|
911
1004
|
loadPlaintext() {
|
|
912
|
-
if (!
|
|
913
|
-
|
|
1005
|
+
if (!existsSync5(this.plaintextFilePath)) {
|
|
1006
|
+
mkdirSync4(this.baseDir, { recursive: true });
|
|
914
1007
|
return;
|
|
915
1008
|
}
|
|
916
1009
|
try {
|
|
917
|
-
const data = JSON.parse(
|
|
1010
|
+
const data = JSON.parse(readFileSync5(this.plaintextFilePath, "utf-8"));
|
|
918
1011
|
this.records = data.records ?? [];
|
|
919
1012
|
} catch {
|
|
920
1013
|
console.error(`[DenialLog] Could not parse ${this.plaintextFilePath}, starting fresh`);
|
|
@@ -922,9 +1015,9 @@ var DenialLog = class {
|
|
|
922
1015
|
}
|
|
923
1016
|
}
|
|
924
1017
|
loadEncrypted() {
|
|
925
|
-
if (!
|
|
1018
|
+
if (!existsSync5(this.encryptedFilePath)) return;
|
|
926
1019
|
try {
|
|
927
|
-
const data = JSON.parse(
|
|
1020
|
+
const data = JSON.parse(readFileSync5(this.encryptedFilePath, "utf-8"));
|
|
928
1021
|
const logFile = JSON.parse(this.decrypt(data.blob));
|
|
929
1022
|
this.records = logFile.records ?? [];
|
|
930
1023
|
} catch (err) {
|
|
@@ -938,23 +1031,23 @@ var DenialLog = class {
|
|
|
938
1031
|
}
|
|
939
1032
|
persistPlaintext() {
|
|
940
1033
|
const data = { version: 1, records: this.records };
|
|
941
|
-
|
|
942
|
-
|
|
1034
|
+
mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
|
|
1035
|
+
writeFileSync4(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
943
1036
|
}
|
|
944
1037
|
persistEncrypted() {
|
|
945
1038
|
const logFile = { version: 1, records: this.records };
|
|
946
1039
|
const data = { version: 1, blob: this.encrypt(JSON.stringify(logFile)) };
|
|
947
|
-
|
|
948
|
-
|
|
1040
|
+
mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
|
|
1041
|
+
writeFileSync4(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
949
1042
|
}
|
|
950
1043
|
};
|
|
951
1044
|
|
|
952
1045
|
// src/lib/receipt-archive.ts
|
|
953
|
-
import { mkdirSync as
|
|
1046
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6, unlinkSync as unlinkSync5 } from "fs";
|
|
954
1047
|
import { homedir as homedir4 } from "os";
|
|
955
|
-
import { dirname as
|
|
1048
|
+
import { dirname as dirname5, join as join6 } from "path";
|
|
956
1049
|
import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes4 } from "crypto";
|
|
957
|
-
var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ??
|
|
1050
|
+
var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ?? join6(homedir4(), ".suveren");
|
|
958
1051
|
function stripPreviews(proposal) {
|
|
959
1052
|
const args = proposal.toolArgs;
|
|
960
1053
|
if (!args || typeof args !== "object") return proposal;
|
|
@@ -968,7 +1061,7 @@ var ReceiptArchive = class {
|
|
|
968
1061
|
vaultKey = null;
|
|
969
1062
|
constructor(filePath) {
|
|
970
1063
|
if (filePath && filePath.endsWith(".json")) {
|
|
971
|
-
this.baseDir =
|
|
1064
|
+
this.baseDir = dirname5(filePath);
|
|
972
1065
|
} else {
|
|
973
1066
|
this.baseDir = filePath ?? DEFAULT_DIR4;
|
|
974
1067
|
}
|
|
@@ -979,13 +1072,13 @@ var ReceiptArchive = class {
|
|
|
979
1072
|
*/
|
|
980
1073
|
setVaultKey(key) {
|
|
981
1074
|
this.vaultKey = key;
|
|
982
|
-
if (
|
|
1075
|
+
if (existsSync6(this.encryptedFilePath)) {
|
|
983
1076
|
this.loadEncrypted();
|
|
984
1077
|
} else if (this.data.receipts.length > 0 || Object.keys(this.data.authorizations).length > 0) {
|
|
985
1078
|
this.persistEncrypted();
|
|
986
|
-
if (
|
|
1079
|
+
if (existsSync6(this.plaintextFilePath)) {
|
|
987
1080
|
try {
|
|
988
|
-
|
|
1081
|
+
unlinkSync5(this.plaintextFilePath);
|
|
989
1082
|
} catch {
|
|
990
1083
|
}
|
|
991
1084
|
}
|
|
@@ -997,7 +1090,7 @@ var ReceiptArchive = class {
|
|
|
997
1090
|
* this state — that would report a hollow success over unreadable evidence.
|
|
998
1091
|
*/
|
|
999
1092
|
isLocked() {
|
|
1000
|
-
return this.vaultKey === null &&
|
|
1093
|
+
return this.vaultKey === null && existsSync6(this.encryptedFilePath);
|
|
1001
1094
|
}
|
|
1002
1095
|
/**
|
|
1003
1096
|
* Archive a signed receipt (and the grant it was issued under).
|
|
@@ -1098,19 +1191,19 @@ var ReceiptArchive = class {
|
|
|
1098
1191
|
}
|
|
1099
1192
|
// ─── File paths ─────────────────────────────────────────────────────────
|
|
1100
1193
|
get plaintextFilePath() {
|
|
1101
|
-
return
|
|
1194
|
+
return join6(this.baseDir, "receipt-archive.json");
|
|
1102
1195
|
}
|
|
1103
1196
|
get encryptedFilePath() {
|
|
1104
|
-
return
|
|
1197
|
+
return join6(this.baseDir, "receipt-archive.enc.json");
|
|
1105
1198
|
}
|
|
1106
1199
|
// ─── Load / Persist ─────────────────────────────────────────────────────
|
|
1107
1200
|
loadPlaintext() {
|
|
1108
|
-
if (!
|
|
1109
|
-
|
|
1201
|
+
if (!existsSync6(this.plaintextFilePath)) {
|
|
1202
|
+
mkdirSync5(this.baseDir, { recursive: true });
|
|
1110
1203
|
return;
|
|
1111
1204
|
}
|
|
1112
1205
|
try {
|
|
1113
|
-
const raw =
|
|
1206
|
+
const raw = readFileSync6(this.plaintextFilePath, "utf-8");
|
|
1114
1207
|
const parsed = JSON.parse(raw);
|
|
1115
1208
|
this.data = {
|
|
1116
1209
|
version: 1,
|
|
@@ -1120,18 +1213,18 @@ var ReceiptArchive = class {
|
|
|
1120
1213
|
} catch {
|
|
1121
1214
|
console.error(`[ReceiptArchive] Could not parse ${this.plaintextFilePath} \u2014 preserving as .corrupt`);
|
|
1122
1215
|
try {
|
|
1123
|
-
|
|
1216
|
+
writeFileSync5(
|
|
1124
1217
|
`${this.plaintextFilePath}.corrupt-${Date.now()}`,
|
|
1125
|
-
|
|
1218
|
+
readFileSync6(this.plaintextFilePath)
|
|
1126
1219
|
);
|
|
1127
1220
|
} catch {
|
|
1128
1221
|
}
|
|
1129
1222
|
}
|
|
1130
1223
|
}
|
|
1131
1224
|
loadEncrypted() {
|
|
1132
|
-
if (!
|
|
1225
|
+
if (!existsSync6(this.encryptedFilePath)) return;
|
|
1133
1226
|
try {
|
|
1134
|
-
const raw =
|
|
1227
|
+
const raw = readFileSync6(this.encryptedFilePath, "utf-8");
|
|
1135
1228
|
const data = JSON.parse(raw);
|
|
1136
1229
|
const decrypted = this.decrypt(data.blob);
|
|
1137
1230
|
const parsed = JSON.parse(decrypted);
|
|
@@ -1143,9 +1236,9 @@ var ReceiptArchive = class {
|
|
|
1143
1236
|
} catch (err) {
|
|
1144
1237
|
console.error(`[ReceiptArchive] Could not decrypt ${this.encryptedFilePath} \u2014 preserving as .corrupt:`, err);
|
|
1145
1238
|
try {
|
|
1146
|
-
|
|
1239
|
+
writeFileSync5(
|
|
1147
1240
|
`${this.encryptedFilePath}.corrupt-${Date.now()}`,
|
|
1148
|
-
|
|
1241
|
+
readFileSync6(this.encryptedFilePath)
|
|
1149
1242
|
);
|
|
1150
1243
|
} catch {
|
|
1151
1244
|
}
|
|
@@ -1159,29 +1252,29 @@ var ReceiptArchive = class {
|
|
|
1159
1252
|
}
|
|
1160
1253
|
}
|
|
1161
1254
|
persistPlaintext() {
|
|
1162
|
-
|
|
1163
|
-
|
|
1255
|
+
mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
|
|
1256
|
+
writeFileSync5(this.plaintextFilePath, JSON.stringify(this.data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1164
1257
|
}
|
|
1165
1258
|
persistEncrypted() {
|
|
1166
1259
|
const data = {
|
|
1167
1260
|
version: 1,
|
|
1168
1261
|
blob: this.encrypt(JSON.stringify(this.data))
|
|
1169
1262
|
};
|
|
1170
|
-
|
|
1171
|
-
|
|
1263
|
+
mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
|
|
1264
|
+
writeFileSync5(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1172
1265
|
}
|
|
1173
1266
|
};
|
|
1174
1267
|
|
|
1175
1268
|
// src/lib/execution-journal.ts
|
|
1176
|
-
import { mkdirSync as
|
|
1269
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync7, renameSync } from "fs";
|
|
1177
1270
|
import { homedir as homedir5 } from "os";
|
|
1178
|
-
import { dirname as
|
|
1179
|
-
import { createHash } from "crypto";
|
|
1180
|
-
var DEFAULT_DIR5 = process.env.SUVEREN_DATA_DIR ??
|
|
1271
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
1272
|
+
import { createHash as createHash2 } from "crypto";
|
|
1273
|
+
var DEFAULT_DIR5 = process.env.SUVEREN_DATA_DIR ?? join7(homedir5(), ".suveren");
|
|
1181
1274
|
var FILE_NAME = "execution-journal.json";
|
|
1182
1275
|
var MAX_AGE_SECONDS2 = 90 * 24 * 60 * 60;
|
|
1183
1276
|
function hashToolArgs(args) {
|
|
1184
|
-
return "sha256:" +
|
|
1277
|
+
return "sha256:" + createHash2("sha256").update(stableStringify(args)).digest("hex");
|
|
1185
1278
|
}
|
|
1186
1279
|
function stableStringify(value) {
|
|
1187
1280
|
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
|
|
@@ -1193,8 +1286,8 @@ function stableStringify(value) {
|
|
|
1193
1286
|
var ExecutionJournal = class {
|
|
1194
1287
|
filePath;
|
|
1195
1288
|
constructor(filePath) {
|
|
1196
|
-
const baseDir = filePath && filePath.endsWith(".json") ?
|
|
1197
|
-
this.filePath =
|
|
1289
|
+
const baseDir = filePath && filePath.endsWith(".json") ? dirname6(filePath) : filePath ?? DEFAULT_DIR5;
|
|
1290
|
+
this.filePath = join7(baseDir, FILE_NAME);
|
|
1198
1291
|
}
|
|
1199
1292
|
/** Look a ticket up. Always reads from disk — another process may have written. */
|
|
1200
1293
|
get(ticketId) {
|
|
@@ -1233,9 +1326,9 @@ var ExecutionJournal = class {
|
|
|
1233
1326
|
}
|
|
1234
1327
|
// ─── Persistence ────────────────────────────────────────────────────────
|
|
1235
1328
|
load() {
|
|
1236
|
-
if (!
|
|
1329
|
+
if (!existsSync7(this.filePath)) return { version: 1, entries: [] };
|
|
1237
1330
|
try {
|
|
1238
|
-
const parsed = JSON.parse(
|
|
1331
|
+
const parsed = JSON.parse(readFileSync7(this.filePath, "utf8"));
|
|
1239
1332
|
if (parsed?.version !== 1 || !Array.isArray(parsed.entries)) {
|
|
1240
1333
|
throw new Error("unexpected shape");
|
|
1241
1334
|
}
|
|
@@ -1249,9 +1342,9 @@ var ExecutionJournal = class {
|
|
|
1249
1342
|
persist(file) {
|
|
1250
1343
|
const cutoff = nowSec() - MAX_AGE_SECONDS2;
|
|
1251
1344
|
file.entries = file.entries.filter((e) => e.startedAt >= cutoff);
|
|
1252
|
-
|
|
1345
|
+
mkdirSync6(dirname6(this.filePath), { recursive: true, mode: 448 });
|
|
1253
1346
|
const tmp = this.filePath + ".tmp";
|
|
1254
|
-
|
|
1347
|
+
writeFileSync6(tmp, JSON.stringify(file, null, 2), { mode: 384 });
|
|
1255
1348
|
renameSync(tmp, this.filePath);
|
|
1256
1349
|
}
|
|
1257
1350
|
};
|
|
@@ -1259,6 +1352,61 @@ function nowSec() {
|
|
|
1259
1352
|
return Math.floor(Date.now() / 1e3);
|
|
1260
1353
|
}
|
|
1261
1354
|
|
|
1355
|
+
// src/lib/proposal-submission-store.ts
|
|
1356
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync8, renameSync as renameSync2 } from "fs";
|
|
1357
|
+
import { homedir as homedir6 } from "os";
|
|
1358
|
+
import { dirname as dirname7, join as join8 } from "path";
|
|
1359
|
+
var DEFAULT_DIR6 = process.env.SUVEREN_DATA_DIR ?? join8(homedir6(), ".suveren");
|
|
1360
|
+
var FILE_NAME2 = "proposal-submissions.json";
|
|
1361
|
+
var MAX_AGE_SECONDS3 = 90 * 24 * 60 * 60;
|
|
1362
|
+
function nowSec2() {
|
|
1363
|
+
return Math.floor(Date.now() / 1e3);
|
|
1364
|
+
}
|
|
1365
|
+
var ProposalSubmissionStore = class {
|
|
1366
|
+
filePath;
|
|
1367
|
+
constructor(filePath) {
|
|
1368
|
+
const baseDir = filePath && filePath.endsWith(".json") ? dirname7(filePath) : filePath ?? DEFAULT_DIR6;
|
|
1369
|
+
this.filePath = join8(baseDir, FILE_NAME2);
|
|
1370
|
+
}
|
|
1371
|
+
/** Record what was submitted, right after a successful submitProposal(). */
|
|
1372
|
+
record(entry) {
|
|
1373
|
+
const file = this.load();
|
|
1374
|
+
file.entries = file.entries.filter((e) => e.proposalId !== entry.proposalId);
|
|
1375
|
+
file.entries.push({
|
|
1376
|
+
proposalId: entry.proposalId,
|
|
1377
|
+
tool: entry.tool,
|
|
1378
|
+
toolArgsHash: hashToolArgs(entry.toolArgs),
|
|
1379
|
+
executionContextHash: hashToolArgs(entry.executionContext),
|
|
1380
|
+
authorizationId: entry.authorizationId,
|
|
1381
|
+
profileId: entry.profileId,
|
|
1382
|
+
submittedAt: nowSec2()
|
|
1383
|
+
});
|
|
1384
|
+
this.persist(file);
|
|
1385
|
+
}
|
|
1386
|
+
/** Always reads from disk — another process (the poll loop lives in the
|
|
1387
|
+
* same process, but this stays consistent with execution-journal.ts). */
|
|
1388
|
+
get(proposalId) {
|
|
1389
|
+
return this.load().entries.find((e) => e.proposalId === proposalId);
|
|
1390
|
+
}
|
|
1391
|
+
load() {
|
|
1392
|
+
if (!existsSync8(this.filePath)) return { version: 1, entries: [] };
|
|
1393
|
+
try {
|
|
1394
|
+
const parsed = JSON.parse(readFileSync8(this.filePath, "utf-8"));
|
|
1395
|
+
const cutoff = nowSec2() - MAX_AGE_SECONDS3;
|
|
1396
|
+
parsed.entries = (parsed.entries ?? []).filter((e) => e.submittedAt >= cutoff);
|
|
1397
|
+
return parsed;
|
|
1398
|
+
} catch {
|
|
1399
|
+
return { version: 1, entries: [] };
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
persist(file) {
|
|
1403
|
+
mkdirSync7(dirname7(this.filePath), { recursive: true, mode: 448 });
|
|
1404
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
1405
|
+
writeFileSync7(tmpPath, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1406
|
+
renameSync2(tmpPath, this.filePath);
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1262
1410
|
// src/lib/gatekeeper.ts
|
|
1263
1411
|
import { verify } from "@hap/core";
|
|
1264
1412
|
var MCPGatekeeper = class {
|
|
@@ -1309,7 +1457,26 @@ var MCPGatekeeper = class {
|
|
|
1309
1457
|
authorization: auth
|
|
1310
1458
|
};
|
|
1311
1459
|
}
|
|
1312
|
-
|
|
1460
|
+
let publicKeyHex;
|
|
1461
|
+
try {
|
|
1462
|
+
publicKeyHex = await this.cache.getPublicKey();
|
|
1463
|
+
} catch (err) {
|
|
1464
|
+
if (err instanceof AsKeyMismatchError) {
|
|
1465
|
+
void notifyControlPlane("as-key-mismatch");
|
|
1466
|
+
return {
|
|
1467
|
+
result: {
|
|
1468
|
+
approved: false,
|
|
1469
|
+
// No dedicated GatekeeperError code exists for this (hap-core's
|
|
1470
|
+
// union predates gateway-side key pinning) — INVALID_SIGNATURE is
|
|
1471
|
+
// the closest fit: it's exactly the claim being made here ("we
|
|
1472
|
+
// will not trust a signature made under this key").
|
|
1473
|
+
errors: [{ code: "INVALID_SIGNATURE", message: err.message }]
|
|
1474
|
+
},
|
|
1475
|
+
authorization: auth
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
throw err;
|
|
1479
|
+
}
|
|
1313
1480
|
const resolvedBounds = override?.bounds ?? auth.bounds ?? auth.frame;
|
|
1314
1481
|
const resolvedContext = override?.context ?? auth.context;
|
|
1315
1482
|
const frame = { ...resolvedBounds, profile: auth.profileId };
|
|
@@ -1341,15 +1508,25 @@ var SharedState = class {
|
|
|
1341
1508
|
receiptArchive;
|
|
1342
1509
|
/** Which tickets this Gatekeeper has executed — the "one execution per ticket" half of exactly-once. */
|
|
1343
1510
|
executionJournal;
|
|
1511
|
+
/** What THIS gateway submitted for each review-mode proposal it created —
|
|
1512
|
+
* see ticket-verify.ts / commitments.ts. */
|
|
1513
|
+
proposalSubmissions;
|
|
1344
1514
|
gatekeeper;
|
|
1345
|
-
|
|
1515
|
+
/**
|
|
1516
|
+
* @param dataDir Passed to the AttestationCache so it can enforce AS key
|
|
1517
|
+
* pinning (as-pairing.ts). Optional for backward compat with existing
|
|
1518
|
+
* constructions/tests that pass only a URL — those get unpinned
|
|
1519
|
+
* trust-on-first-use behavior, same as before pinning existed.
|
|
1520
|
+
*/
|
|
1521
|
+
constructor(spUrl2, gateStorePath, dataDir2) {
|
|
1346
1522
|
this.spClient = new SPClient(spUrl2);
|
|
1347
|
-
this.cache = new AttestationCache(this.spClient);
|
|
1523
|
+
this.cache = new AttestationCache(this.spClient, dataDir2);
|
|
1348
1524
|
this.gateStore = new GateStore(gateStorePath);
|
|
1349
1525
|
this.executionLog = new ExecutionLog(gateStorePath);
|
|
1350
1526
|
this.denialLog = new DenialLog(gateStorePath);
|
|
1351
1527
|
this.receiptArchive = new ReceiptArchive(gateStorePath);
|
|
1352
1528
|
this.executionJournal = new ExecutionJournal(gateStorePath);
|
|
1529
|
+
this.proposalSubmissions = new ProposalSubmissionStore(gateStorePath);
|
|
1353
1530
|
this.gatekeeper = new MCPGatekeeper(this.cache);
|
|
1354
1531
|
}
|
|
1355
1532
|
/**
|
|
@@ -1365,7 +1542,8 @@ var SharedState = class {
|
|
|
1365
1542
|
let asPublicKey;
|
|
1366
1543
|
try {
|
|
1367
1544
|
asPublicKey = await this.cache.getPublicKey();
|
|
1368
|
-
} catch {
|
|
1545
|
+
} catch (err) {
|
|
1546
|
+
if (err instanceof AsKeyMismatchError) throw err;
|
|
1369
1547
|
}
|
|
1370
1548
|
this.receiptArchive.record({
|
|
1371
1549
|
receipt,
|
|
@@ -1387,6 +1565,7 @@ var SharedState = class {
|
|
|
1387
1565
|
} : void 0
|
|
1388
1566
|
});
|
|
1389
1567
|
} catch (err) {
|
|
1568
|
+
if (err instanceof AsKeyMismatchError) throw err;
|
|
1390
1569
|
console.error(
|
|
1391
1570
|
"[Suveren MCP] Receipt archive write failed (execution proceeds \u2014 AS retains authoritative copy):",
|
|
1392
1571
|
err
|
|
@@ -1435,6 +1614,7 @@ import { z } from "zod";
|
|
|
1435
1614
|
import { getProfile } from "@hap/core";
|
|
1436
1615
|
|
|
1437
1616
|
// src/lib/consumption.ts
|
|
1617
|
+
import { boundActionTypes } from "@hap/core";
|
|
1438
1618
|
function getConsumptionState(auth, executionLog, profile) {
|
|
1439
1619
|
if (!profile?.boundsSchema?.fields) return [];
|
|
1440
1620
|
const entries = [];
|
|
@@ -1454,7 +1634,8 @@ function getConsumptionState(auth, executionLog, profile) {
|
|
|
1454
1634
|
auth.path,
|
|
1455
1635
|
cumulativeField,
|
|
1456
1636
|
bt.window,
|
|
1457
|
-
now
|
|
1637
|
+
now,
|
|
1638
|
+
boundActionTypes(fieldName, fieldDef)
|
|
1458
1639
|
);
|
|
1459
1640
|
entries.push({
|
|
1460
1641
|
// displayName FIRST: description is prose meant for a human reading the
|
|
@@ -1498,24 +1679,24 @@ function formatConsumptionFull(entries) {
|
|
|
1498
1679
|
}
|
|
1499
1680
|
|
|
1500
1681
|
// src/lib/context-loader.ts
|
|
1501
|
-
import { readFileSync as
|
|
1502
|
-
import { homedir as
|
|
1503
|
-
import { join as
|
|
1504
|
-
var
|
|
1682
|
+
import { readFileSync as readFileSync9, existsSync as existsSync9 } from "fs";
|
|
1683
|
+
import { homedir as homedir7 } from "os";
|
|
1684
|
+
import { join as join9 } from "path";
|
|
1685
|
+
var DEFAULT_DIR7 = process.env.SUVEREN_DATA_DIR ?? join9(homedir7(), ".suveren");
|
|
1505
1686
|
var BRIEF_MAX_CHARS = 16 * 1024;
|
|
1506
|
-
function readContextFile(
|
|
1507
|
-
const dir =
|
|
1508
|
-
const filePath =
|
|
1509
|
-
if (!
|
|
1687
|
+
function readContextFile(dataDir2) {
|
|
1688
|
+
const dir = dataDir2 ?? DEFAULT_DIR7;
|
|
1689
|
+
const filePath = join9(dir, "context.md");
|
|
1690
|
+
if (!existsSync9(filePath)) return null;
|
|
1510
1691
|
try {
|
|
1511
|
-
const content =
|
|
1692
|
+
const content = readFileSync9(filePath, "utf-8").trim();
|
|
1512
1693
|
return content || null;
|
|
1513
1694
|
} catch {
|
|
1514
1695
|
return null;
|
|
1515
1696
|
}
|
|
1516
1697
|
}
|
|
1517
|
-
function getContextForBrief(
|
|
1518
|
-
const full = readContextFile(
|
|
1698
|
+
function getContextForBrief(dataDir2) {
|
|
1699
|
+
const full = readContextFile(dataDir2);
|
|
1519
1700
|
if (!full) return { brief: null, truncated: false };
|
|
1520
1701
|
if (full.length <= BRIEF_MAX_CHARS) {
|
|
1521
1702
|
return { brief: full, truncated: false };
|
|
@@ -1623,9 +1804,28 @@ function expiredSessionNotice(what) {
|
|
|
1623
1804
|
|
|
1624
1805
|
TELL THE USER: open ${uiUrl()} and enter your Suveren API key to sign in again. Your mandates are safe; nothing ran.`;
|
|
1625
1806
|
}
|
|
1807
|
+
function asKeyMismatchNotice(what) {
|
|
1808
|
+
return `${what} Suveren gateway is LOCKED because the Authority Server it is configured to use presented a signing key that does not match the one pinned when this gateway last signed in. This is NOT an ended sign-in \u2014 signing in again will be refused until the mismatch is resolved.
|
|
1809
|
+
|
|
1810
|
+
TELL THE USER: this needs an operator to check whether the Authority Server's key changed intentionally (e.g. a reinstall) or something else is answering at that address, at ${uiUrl()}. Nothing ran under the unrecognized key.`;
|
|
1811
|
+
}
|
|
1812
|
+
function asUrlChangedNotice(what) {
|
|
1813
|
+
return `${what} Suveren gateway is LOCKED because the Authority Server it points at has changed since it last signed in. Cached mandates from the old server were cleared.
|
|
1814
|
+
|
|
1815
|
+
TELL THE USER: open ${uiUrl()} and sign in again to pair with the new Authority Server.`;
|
|
1816
|
+
}
|
|
1626
1817
|
function lockedNotice(action, reason = "restart") {
|
|
1627
1818
|
const what = action ? `Cannot ${action}: the` : "The";
|
|
1628
|
-
|
|
1819
|
+
switch (reason) {
|
|
1820
|
+
case "expired":
|
|
1821
|
+
return expiredSessionNotice(what);
|
|
1822
|
+
case "as-key-mismatch":
|
|
1823
|
+
return asKeyMismatchNotice(what);
|
|
1824
|
+
case "as-url-changed":
|
|
1825
|
+
return asUrlChangedNotice(what);
|
|
1826
|
+
default:
|
|
1827
|
+
return bootLockedNotice(what);
|
|
1828
|
+
}
|
|
1629
1829
|
}
|
|
1630
1830
|
|
|
1631
1831
|
// src/tools/authorizations.ts
|
|
@@ -1634,6 +1834,9 @@ import { getProfile as getProfile4 } from "@hap/core";
|
|
|
1634
1834
|
// src/lib/receipt-footer.ts
|
|
1635
1835
|
import { deriveIdentityLine } from "@hap/core";
|
|
1636
1836
|
var AS_BASE = (process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai").replace(/\/$/, "");
|
|
1837
|
+
function setAsBaseUrl(url) {
|
|
1838
|
+
AS_BASE = url.replace(/\/$/, "");
|
|
1839
|
+
}
|
|
1637
1840
|
var OPERATOR_NAME = process.env.SUVEREN_OPERATOR_NAME ?? "Suveren";
|
|
1638
1841
|
var HAP_URL = "https://www.humanagencyprotocol.org/";
|
|
1639
1842
|
var FOOTER_PROFILES = /* @__PURE__ */ new Set(["email", "calendar", "publish"]);
|
|
@@ -1739,6 +1942,83 @@ function attachReceiptId(tool, args, receiptId) {
|
|
|
1739
1942
|
return { ...args, receipt_id: receiptId };
|
|
1740
1943
|
}
|
|
1741
1944
|
|
|
1945
|
+
// src/lib/ticket-verify.ts
|
|
1946
|
+
import { verifyReceiptSignature } from "@hap/core";
|
|
1947
|
+
var TicketBindingMismatchError = class extends Error {
|
|
1948
|
+
constructor(message) {
|
|
1949
|
+
super(message);
|
|
1950
|
+
this.name = "TicketBindingMismatchError";
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
var TICKET_MAX_AGE_SECONDS = 5 * 60;
|
|
1954
|
+
var TICKET_MAX_CLOCK_SKEW_SECONDS = 30;
|
|
1955
|
+
async function verifyTicket(cache, receipt, expected) {
|
|
1956
|
+
const publicKeyHex = await cache.getPublicKey();
|
|
1957
|
+
if (typeof receipt.signature !== "string" || !receipt.signature) {
|
|
1958
|
+
throw new AsKeyMismatchError("Ticket carries no signature \u2014 refusing to trust it.");
|
|
1959
|
+
}
|
|
1960
|
+
try {
|
|
1961
|
+
await verifyReceiptSignature(receipt, publicKeyHex);
|
|
1962
|
+
} catch (err) {
|
|
1963
|
+
throw new AsKeyMismatchError(
|
|
1964
|
+
`Ticket signature does not verify against the pinned Authority Server key \u2014 ${err instanceof Error ? err.message : String(err)}. Refusing to execute.`
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
if (receipt.action !== expected.action) {
|
|
1968
|
+
throw new TicketBindingMismatchError(
|
|
1969
|
+
`Ticket action "${String(receipt.action)}" does not match the requested action "${expected.action}" \u2014 refusing to execute.`
|
|
1970
|
+
);
|
|
1971
|
+
}
|
|
1972
|
+
if (expected.executionContext !== void 0 && hashToolArgs(receipt.executionContext ?? {}) !== hashToolArgs(expected.executionContext)) {
|
|
1973
|
+
throw new TicketBindingMismatchError(
|
|
1974
|
+
"Ticket executionContext does not match what this call requested \u2014 refusing to execute."
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
if (expected.authorizationId !== void 0 && receipt.authorizationId !== expected.authorizationId) {
|
|
1978
|
+
throw new TicketBindingMismatchError(
|
|
1979
|
+
`Ticket authorizationId "${String(receipt.authorizationId)}" does not match the requested grant "${expected.authorizationId}" \u2014 refusing to execute.`
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
if (expected.profileId !== void 0 && receipt.profileId !== expected.profileId) {
|
|
1983
|
+
throw new TicketBindingMismatchError(
|
|
1984
|
+
`Ticket profileId "${String(receipt.profileId)}" does not match the requested profile "${expected.profileId}" \u2014 refusing to execute.`
|
|
1985
|
+
);
|
|
1986
|
+
}
|
|
1987
|
+
if (expected.proposalId !== void 0 && receipt.proposalId !== expected.proposalId) {
|
|
1988
|
+
throw new TicketBindingMismatchError(
|
|
1989
|
+
`Ticket proposalId "${String(receipt.proposalId)}" does not match the proposal being executed "${expected.proposalId}" \u2014 refusing to execute.`
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
if (expected.contentHash !== void 0) {
|
|
1993
|
+
if (receipt.contentHash !== expected.contentHash) {
|
|
1994
|
+
throw new TicketBindingMismatchError(
|
|
1995
|
+
"Ticket contentHash does not match the content this call is bound to \u2014 refusing to execute."
|
|
1996
|
+
);
|
|
1997
|
+
}
|
|
1998
|
+
if (expected.contentBinding !== void 0 && hashToolArgs(receipt.contentBinding ?? {}) !== hashToolArgs(expected.contentBinding)) {
|
|
1999
|
+
throw new TicketBindingMismatchError(
|
|
2000
|
+
"Ticket contentBinding does not match what this call requested \u2014 refusing to execute."
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
const timestamp = receipt.timestamp;
|
|
2005
|
+
if (typeof timestamp !== "number" || !Number.isFinite(timestamp)) {
|
|
2006
|
+
throw new TicketBindingMismatchError("Ticket carries no valid timestamp \u2014 refusing to execute.");
|
|
2007
|
+
}
|
|
2008
|
+
const nowSec3 = Math.floor(Date.now() / 1e3);
|
|
2009
|
+
const ageSec = nowSec3 - timestamp;
|
|
2010
|
+
if (ageSec > TICKET_MAX_AGE_SECONDS) {
|
|
2011
|
+
throw new TicketBindingMismatchError(
|
|
2012
|
+
`Ticket is ${ageSec}s old, older than the ${TICKET_MAX_AGE_SECONDS}s freshness window \u2014 refusing to execute.`
|
|
2013
|
+
);
|
|
2014
|
+
}
|
|
2015
|
+
if (ageSec < -TICKET_MAX_CLOCK_SKEW_SECONDS) {
|
|
2016
|
+
throw new TicketBindingMismatchError(
|
|
2017
|
+
`Ticket is timestamped ${-ageSec}s in the future, beyond the ${TICKET_MAX_CLOCK_SKEW_SECONDS}s clock-skew tolerance \u2014 refusing to execute.`
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
|
|
1742
2022
|
// src/lib/arg-encoding.ts
|
|
1743
2023
|
function rfc2047Encode(value) {
|
|
1744
2024
|
if (!/[^\x00-\x7F]/.test(value)) return value;
|
|
@@ -2454,6 +2734,14 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
|
|
|
2454
2734
|
toolArgs: enrichedArgs,
|
|
2455
2735
|
executionContext: { ...execution }
|
|
2456
2736
|
});
|
|
2737
|
+
state2.proposalSubmissions.record({
|
|
2738
|
+
proposalId: proposal.id,
|
|
2739
|
+
tool: tool.namespacedName,
|
|
2740
|
+
toolArgs: enrichedArgs,
|
|
2741
|
+
executionContext: { ...execution },
|
|
2742
|
+
authorizationId: authzId,
|
|
2743
|
+
profileId: auth.profileId
|
|
2744
|
+
});
|
|
2457
2745
|
return {
|
|
2458
2746
|
content: [{
|
|
2459
2747
|
type: "text",
|
|
@@ -2496,6 +2784,14 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
2496
2784
|
...binding ? { contentHash: binding.contentHash, contentBinding: binding.contentBinding } : {}
|
|
2497
2785
|
});
|
|
2498
2786
|
receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
|
|
2787
|
+
await verifyTicket(state2.cache, receipt, {
|
|
2788
|
+
action: tool.namespacedName,
|
|
2789
|
+
executionContext: { ...execution },
|
|
2790
|
+
authorizationId: authzId,
|
|
2791
|
+
profileId: auth.profileId,
|
|
2792
|
+
contentHash: binding?.contentHash,
|
|
2793
|
+
contentBinding: binding?.contentBinding
|
|
2794
|
+
});
|
|
2499
2795
|
await state2.archiveReceipt(receipt, {
|
|
2500
2796
|
authorizationId: authzId,
|
|
2501
2797
|
profileId: auth.profileId,
|
|
@@ -2510,6 +2806,13 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
2510
2806
|
boundContent: binding?.boundContent
|
|
2511
2807
|
});
|
|
2512
2808
|
} catch (err) {
|
|
2809
|
+
if (err instanceof AsKeyMismatchError || err instanceof TicketBindingMismatchError) {
|
|
2810
|
+
void notifyControlPlane("as-key-mismatch");
|
|
2811
|
+
return {
|
|
2812
|
+
content: [{ type: "text", text: `Blocked: ${err.message}` }],
|
|
2813
|
+
isError: true
|
|
2814
|
+
};
|
|
2815
|
+
}
|
|
2513
2816
|
if (err instanceof ContentBindingError) {
|
|
2514
2817
|
return {
|
|
2515
2818
|
content: [{
|
|
@@ -2555,6 +2858,14 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
|
|
|
2555
2858
|
executionContext: { ...execution },
|
|
2556
2859
|
pendingApprovers: uniqueApprovers
|
|
2557
2860
|
});
|
|
2861
|
+
state2.proposalSubmissions.record({
|
|
2862
|
+
proposalId: proposal.id,
|
|
2863
|
+
tool: tool.namespacedName,
|
|
2864
|
+
toolArgs: enrichedArgs,
|
|
2865
|
+
executionContext: { ...execution },
|
|
2866
|
+
authorizationId: authzId,
|
|
2867
|
+
profileId: auth.profileId
|
|
2868
|
+
});
|
|
2558
2869
|
return {
|
|
2559
2870
|
content: [{
|
|
2560
2871
|
type: "text",
|
|
@@ -2962,6 +3273,9 @@ function listIntegrationsHandler(state2, integrationManager2) {
|
|
|
2962
3273
|
|
|
2963
3274
|
// src/tools/commitments.ts
|
|
2964
3275
|
import { ContentBindingError as ContentBindingError2 } from "@hap/core";
|
|
3276
|
+
function buildSkippedProposalNote(proposalId) {
|
|
3277
|
+
return `Proposal ${proposalId} was approved, but was submitted from another device/installation of this operator (or one whose local record is gone) \u2014 this gateway will not execute it. Re-run the same request here to execute it from this gateway.`;
|
|
3278
|
+
}
|
|
2965
3279
|
var installedExecutor = null;
|
|
2966
3280
|
function installCommittedExecutor(executor) {
|
|
2967
3281
|
installedExecutor = executor;
|
|
@@ -2987,6 +3301,28 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
2987
3301
|
);
|
|
2988
3302
|
}
|
|
2989
3303
|
const cachedAuth = state2.cache.getAllAuthorizations().find((a) => a.authorizationId === proposal.authorizationId);
|
|
3304
|
+
const submitted = state2.proposalSubmissions.get(proposal.id);
|
|
3305
|
+
if (!submitted) {
|
|
3306
|
+
console.error(
|
|
3307
|
+
`[Suveren MCP] Proposal ${proposal.id} is committed but has no local submission record on this gateway \u2014 leaving it for whichever gateway submitted it (this is normal for a different device of the same operator, or the AS lists a proposal we never submitted).`
|
|
3308
|
+
);
|
|
3309
|
+
return { text: buildSkippedProposalNote(proposal.id) };
|
|
3310
|
+
}
|
|
3311
|
+
{
|
|
3312
|
+
const mismatches = [];
|
|
3313
|
+
if (submitted.tool !== proposal.tool) mismatches.push("tool");
|
|
3314
|
+
if (submitted.toolArgsHash !== hashToolArgs(proposal.toolArgs)) mismatches.push("arguments");
|
|
3315
|
+
if (submitted.executionContextHash !== hashToolArgs(proposal.executionContext)) mismatches.push("executionContext");
|
|
3316
|
+
if (submitted.authorizationId !== proposal.authorizationId) mismatches.push("authorizationId");
|
|
3317
|
+
if (submitted.profileId !== proposal.profileId) mismatches.push("profileId");
|
|
3318
|
+
if (mismatches.length > 0) {
|
|
3319
|
+
void notifyControlPlane("as-key-mismatch");
|
|
3320
|
+
return {
|
|
3321
|
+
text: `Blocked: proposal ${proposal.id} no longer matches what this gateway submitted (${mismatches.join(", ")} differ) \u2014 refusing to execute.`,
|
|
3322
|
+
isError: true
|
|
3323
|
+
};
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
2990
3326
|
let receiptId;
|
|
2991
3327
|
let replayed = false;
|
|
2992
3328
|
try {
|
|
@@ -3022,6 +3358,15 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
3022
3358
|
});
|
|
3023
3359
|
receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
|
|
3024
3360
|
replayed = idempotent;
|
|
3361
|
+
await verifyTicket(state2.cache, receipt, {
|
|
3362
|
+
action: proposal.tool,
|
|
3363
|
+
executionContext: proposal.executionContext,
|
|
3364
|
+
authorizationId: proposal.authorizationId,
|
|
3365
|
+
profileId: proposal.profileId,
|
|
3366
|
+
proposalId: proposal.id,
|
|
3367
|
+
contentHash: binding?.contentHash,
|
|
3368
|
+
contentBinding: binding?.contentBinding
|
|
3369
|
+
});
|
|
3025
3370
|
await state2.archiveReceipt(receipt, {
|
|
3026
3371
|
authorizationId: proposal.authorizationId,
|
|
3027
3372
|
profileId: proposal.profileId,
|
|
@@ -3036,6 +3381,13 @@ async function executeCommitted(proposal, state2, integrationManager2) {
|
|
|
3036
3381
|
boundContent: binding?.boundContent
|
|
3037
3382
|
});
|
|
3038
3383
|
} catch (err) {
|
|
3384
|
+
if (err instanceof AsKeyMismatchError || err instanceof TicketBindingMismatchError) {
|
|
3385
|
+
void notifyControlPlane("as-key-mismatch");
|
|
3386
|
+
return {
|
|
3387
|
+
text: `Proposal ${proposal.id}: blocked \u2014 ${err.message}`,
|
|
3388
|
+
isError: true
|
|
3389
|
+
};
|
|
3390
|
+
}
|
|
3039
3391
|
if (err instanceof ContentBindingError2) {
|
|
3040
3392
|
return {
|
|
3041
3393
|
text: `Proposal ${proposal.id}: blocked \u2014 the approved content cannot be bound to the receipt. ${err.message}`,
|
|
@@ -3195,9 +3547,13 @@ Wait for the human to approve; do not re-submit the tool call.`
|
|
|
3195
3547
|
}]
|
|
3196
3548
|
};
|
|
3197
3549
|
}
|
|
3198
|
-
const lines = committed.map(
|
|
3199
|
-
|
|
3200
|
-
|
|
3550
|
+
const lines = committed.map((p) => {
|
|
3551
|
+
const base = `${p.id}: tool=${p.tool}, status=${p.status}, committed=[${Object.keys(p.committedBy).join(",")}]`;
|
|
3552
|
+
if (p.status === "committed" && !state2.proposalSubmissions.get(p.id)) {
|
|
3553
|
+
return `${base} \u2014 SKIPPED HERE: ${buildSkippedProposalNote(p.id)}`;
|
|
3554
|
+
}
|
|
3555
|
+
return base;
|
|
3556
|
+
});
|
|
3201
3557
|
return {
|
|
3202
3558
|
content: [{
|
|
3203
3559
|
type: "text",
|
|
@@ -3394,16 +3750,16 @@ function verifyGateContentHashes(content, auth) {
|
|
|
3394
3750
|
}
|
|
3395
3751
|
|
|
3396
3752
|
// src/lib/integration-registry.ts
|
|
3397
|
-
import { mkdirSync as
|
|
3398
|
-
import { homedir as
|
|
3399
|
-
import { dirname as
|
|
3400
|
-
var DEFAULT_DATA_DIR = process.env.SUVEREN_DATA_DIR ??
|
|
3753
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync8, existsSync as existsSync10 } from "fs";
|
|
3754
|
+
import { homedir as homedir8 } from "os";
|
|
3755
|
+
import { dirname as dirname8, join as join10 } from "path";
|
|
3756
|
+
var DEFAULT_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join10(homedir8(), ".suveren");
|
|
3401
3757
|
var IntegrationRegistry = class {
|
|
3402
3758
|
integrations = /* @__PURE__ */ new Map();
|
|
3403
3759
|
filePath;
|
|
3404
|
-
constructor(
|
|
3405
|
-
const dir =
|
|
3406
|
-
this.filePath =
|
|
3760
|
+
constructor(dataDir2) {
|
|
3761
|
+
const dir = dataDir2 ?? DEFAULT_DATA_DIR;
|
|
3762
|
+
this.filePath = join10(dir, "integrations.json");
|
|
3407
3763
|
this.load();
|
|
3408
3764
|
}
|
|
3409
3765
|
// ─── CRUD ───────────────────────────────────────────────────────────────
|
|
@@ -3434,12 +3790,12 @@ var IntegrationRegistry = class {
|
|
|
3434
3790
|
}
|
|
3435
3791
|
// ─── Load / Save ────────────────────────────────────────────────────────
|
|
3436
3792
|
load() {
|
|
3437
|
-
if (!
|
|
3438
|
-
|
|
3793
|
+
if (!existsSync10(this.filePath)) {
|
|
3794
|
+
mkdirSync8(dirname8(this.filePath), { recursive: true });
|
|
3439
3795
|
return;
|
|
3440
3796
|
}
|
|
3441
3797
|
try {
|
|
3442
|
-
const raw =
|
|
3798
|
+
const raw = readFileSync10(this.filePath, "utf-8");
|
|
3443
3799
|
const data = JSON.parse(raw);
|
|
3444
3800
|
const migrated = data.integrations.map((i) => {
|
|
3445
3801
|
if ("toolGating" in i && !("profile" in i)) {
|
|
@@ -3468,45 +3824,45 @@ var IntegrationRegistry = class {
|
|
|
3468
3824
|
version: 1,
|
|
3469
3825
|
integrations: Array.from(this.integrations.values())
|
|
3470
3826
|
};
|
|
3471
|
-
|
|
3472
|
-
|
|
3827
|
+
mkdirSync8(dirname8(this.filePath), { recursive: true });
|
|
3828
|
+
writeFileSync8(this.filePath, JSON.stringify(data, null, 2), { encoding: "utf-8" });
|
|
3473
3829
|
}
|
|
3474
3830
|
};
|
|
3475
3831
|
|
|
3476
3832
|
// src/lib/integration-manager.ts
|
|
3477
|
-
import { homedir as
|
|
3478
|
-
import { join as
|
|
3479
|
-
import { existsSync as
|
|
3833
|
+
import { homedir as homedir9 } from "os";
|
|
3834
|
+
import { join as join12, delimiter } from "path";
|
|
3835
|
+
import { existsSync as existsSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync12, rmSync } from "fs";
|
|
3480
3836
|
import { execFile } from "child_process";
|
|
3481
3837
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3482
3838
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3483
3839
|
import { getProfile as getProfile5 } from "@hap/core";
|
|
3484
3840
|
|
|
3485
3841
|
// src/lib/manifest-loader.ts
|
|
3486
|
-
import { readFileSync as
|
|
3487
|
-
import { join as
|
|
3842
|
+
import { readFileSync as readFileSync11, existsSync as existsSync11 } from "fs";
|
|
3843
|
+
import { join as join11, resolve } from "path";
|
|
3488
3844
|
var manifests = /* @__PURE__ */ new Map();
|
|
3489
3845
|
function loadManifests(integrationsDir) {
|
|
3490
3846
|
const dir = resolve(
|
|
3491
|
-
integrationsDir ?? process.env.SUVEREN_MANIFESTS_DIR ??
|
|
3847
|
+
integrationsDir ?? process.env.SUVEREN_MANIFESTS_DIR ?? join11(import.meta.dirname ?? __dirname, "..", "..", "..", "..", "content", "integrations")
|
|
3492
3848
|
);
|
|
3493
|
-
const indexPath =
|
|
3494
|
-
if (!
|
|
3849
|
+
const indexPath = join11(dir, "index.json");
|
|
3850
|
+
if (!existsSync11(indexPath)) {
|
|
3495
3851
|
console.error(`[ManifestLoader] No index.json found at ${indexPath}, skipping manifest loading`);
|
|
3496
3852
|
return 0;
|
|
3497
3853
|
}
|
|
3498
3854
|
let index;
|
|
3499
3855
|
try {
|
|
3500
|
-
index = JSON.parse(
|
|
3856
|
+
index = JSON.parse(readFileSync11(indexPath, "utf-8"));
|
|
3501
3857
|
} catch (err) {
|
|
3502
3858
|
console.error(`[ManifestLoader] Failed to parse ${indexPath}:`, err);
|
|
3503
3859
|
return 0;
|
|
3504
3860
|
}
|
|
3505
3861
|
let loaded = 0;
|
|
3506
3862
|
for (const [id, relativePath] of Object.entries(index.integrations)) {
|
|
3507
|
-
const manifestPath =
|
|
3863
|
+
const manifestPath = join11(dir, relativePath);
|
|
3508
3864
|
try {
|
|
3509
|
-
const manifest = JSON.parse(
|
|
3865
|
+
const manifest = JSON.parse(readFileSync11(manifestPath, "utf-8"));
|
|
3510
3866
|
manifests.set(id, manifest);
|
|
3511
3867
|
loaded++;
|
|
3512
3868
|
} catch (err) {
|
|
@@ -3594,26 +3950,26 @@ function safeHost(url) {
|
|
|
3594
3950
|
}
|
|
3595
3951
|
|
|
3596
3952
|
// src/lib/integration-manager.ts
|
|
3597
|
-
var DEFAULT_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ??
|
|
3598
|
-
var INTEGRATIONS_DIR = process.env.SUVEREN_INTEGRATIONS_DIR ??
|
|
3953
|
+
var DEFAULT_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join12(homedir9(), ".suveren");
|
|
3954
|
+
var INTEGRATIONS_DIR = process.env.SUVEREN_INTEGRATIONS_DIR ?? join12(DEFAULT_DATA_DIR2, "integrations");
|
|
3599
3955
|
var installLock = Promise.resolve();
|
|
3600
3956
|
function withInstallLock(task) {
|
|
3601
3957
|
const run = installLock.then(task, task);
|
|
3602
3958
|
installLock = run.then(() => void 0, () => void 0);
|
|
3603
3959
|
return run;
|
|
3604
3960
|
}
|
|
3605
|
-
var INTEGRATIONS_BIN =
|
|
3961
|
+
var INTEGRATIONS_BIN = join12(INTEGRATIONS_DIR, "node_modules", ".bin");
|
|
3606
3962
|
function buildPath() {
|
|
3607
3963
|
const base = process.env.PATH ?? "";
|
|
3608
3964
|
return [INTEGRATIONS_BIN, base].join(delimiter);
|
|
3609
3965
|
}
|
|
3610
3966
|
function ensureIntegrationsDir() {
|
|
3611
|
-
if (!
|
|
3612
|
-
|
|
3967
|
+
if (!existsSync12(INTEGRATIONS_DIR)) {
|
|
3968
|
+
mkdirSync9(INTEGRATIONS_DIR, { recursive: true });
|
|
3613
3969
|
}
|
|
3614
|
-
const pkgPath =
|
|
3615
|
-
if (!
|
|
3616
|
-
|
|
3970
|
+
const pkgPath = join12(INTEGRATIONS_DIR, "package.json");
|
|
3971
|
+
if (!existsSync12(pkgPath)) {
|
|
3972
|
+
writeFileSync9(pkgPath, JSON.stringify({ name: "suveren-integrations", version: "1.0.0", private: true }, null, 2));
|
|
3617
3973
|
}
|
|
3618
3974
|
}
|
|
3619
3975
|
function readAgeOf(config) {
|
|
@@ -3679,19 +4035,19 @@ var IntegrationManager = class {
|
|
|
3679
4035
|
* exist, and treat anything else as not-installed (and reinstallable).
|
|
3680
4036
|
*/
|
|
3681
4037
|
isUsableInstall(npmPackage) {
|
|
3682
|
-
const pkgDir =
|
|
3683
|
-
const pkgJson =
|
|
3684
|
-
if (!
|
|
4038
|
+
const pkgDir = join12(INTEGRATIONS_DIR, "node_modules", ...npmPackage.split("/"));
|
|
4039
|
+
const pkgJson = join12(pkgDir, "package.json");
|
|
4040
|
+
if (!existsSync12(pkgDir) || !existsSync12(pkgJson)) return false;
|
|
3685
4041
|
try {
|
|
3686
|
-
const pkg = JSON.parse(
|
|
4042
|
+
const pkg = JSON.parse(readFileSync12(pkgJson, "utf8"));
|
|
3687
4043
|
const defaultBinName = (pkg.name ?? npmPackage).split("/").pop() ?? "";
|
|
3688
4044
|
const binMap = typeof pkg.bin === "string" ? { [defaultBinName]: pkg.bin } : pkg.bin ?? {};
|
|
3689
4045
|
const binEntries = Object.entries(binMap);
|
|
3690
4046
|
for (const [binName, target] of binEntries) {
|
|
3691
|
-
if (!
|
|
4047
|
+
if (!existsSync12(join12(pkgDir, target))) return false;
|
|
3692
4048
|
if (!this.binShimExists(binName)) return false;
|
|
3693
4049
|
}
|
|
3694
|
-
if (binEntries.length === 0 && pkg.main && !
|
|
4050
|
+
if (binEntries.length === 0 && pkg.main && !existsSync12(join12(pkgDir, pkg.main))) return false;
|
|
3695
4051
|
return true;
|
|
3696
4052
|
} catch {
|
|
3697
4053
|
return false;
|
|
@@ -3705,7 +4061,7 @@ var IntegrationManager = class {
|
|
|
3705
4061
|
binShimExists(binName) {
|
|
3706
4062
|
if (!binName) return false;
|
|
3707
4063
|
const candidates = process.platform === "win32" ? [binName, `${binName}.cmd`, `${binName}.CMD`, `${binName}.ps1`] : [binName];
|
|
3708
|
-
return candidates.some((c) =>
|
|
4064
|
+
return candidates.some((c) => existsSync12(join12(INTEGRATIONS_BIN, c)));
|
|
3709
4065
|
}
|
|
3710
4066
|
/**
|
|
3711
4067
|
* Install an npm package into the managed integrations directory if not
|
|
@@ -3729,8 +4085,8 @@ var IntegrationManager = class {
|
|
|
3729
4085
|
}
|
|
3730
4086
|
/** The actual install. Callers MUST hold the install lock. */
|
|
3731
4087
|
async installNow(npmPackage) {
|
|
3732
|
-
const pkgDir =
|
|
3733
|
-
if (
|
|
4088
|
+
const pkgDir = join12(INTEGRATIONS_DIR, "node_modules", ...npmPackage.split("/"));
|
|
4089
|
+
if (existsSync12(pkgDir)) {
|
|
3734
4090
|
console.error(`[IntegrationManager] Removing unusable install of ${npmPackage}`);
|
|
3735
4091
|
try {
|
|
3736
4092
|
rmSync(pkgDir, { recursive: true, force: true });
|
|
@@ -3844,6 +4200,11 @@ var IntegrationManager = class {
|
|
|
3844
4200
|
const transport = new StdioClientTransport({
|
|
3845
4201
|
command: config.command,
|
|
3846
4202
|
args,
|
|
4203
|
+
// `...process.env` is also how a saved `--ca-file` reaches an
|
|
4204
|
+
// integration: NODE_EXTRA_CA_CERTS (read by Node only at process
|
|
4205
|
+
// start) is already set on THIS process by bundle/server.js before
|
|
4206
|
+
// the MCP server ever starts, so every integration this manager spawns
|
|
4207
|
+
// inherits it here for free — no separate handling needed.
|
|
3847
4208
|
env: {
|
|
3848
4209
|
...process.env,
|
|
3849
4210
|
PATH: buildPath(),
|
|
@@ -4160,28 +4521,28 @@ var IntegrationManager = class {
|
|
|
4160
4521
|
};
|
|
4161
4522
|
|
|
4162
4523
|
// src/lib/profile-loader.ts
|
|
4163
|
-
import { readFileSync as
|
|
4164
|
-
import { join as
|
|
4524
|
+
import { readFileSync as readFileSync13, existsSync as existsSync13 } from "fs";
|
|
4525
|
+
import { join as join13, resolve as resolve2 } from "path";
|
|
4165
4526
|
import { registerProfile } from "@hap/core";
|
|
4166
4527
|
function loadProfiles(profilesDir) {
|
|
4167
|
-
const dir = resolve2(profilesDir ?? process.env.SUVEREN_PROFILES_DIR ??
|
|
4168
|
-
const indexPath =
|
|
4169
|
-
if (!
|
|
4528
|
+
const dir = resolve2(profilesDir ?? process.env.SUVEREN_PROFILES_DIR ?? join13(import.meta.dirname ?? __dirname, "..", "..", "..", "..", "..", "hap-profiles"));
|
|
4529
|
+
const indexPath = join13(dir, "index.json");
|
|
4530
|
+
if (!existsSync13(indexPath)) {
|
|
4170
4531
|
warnNoProfiles(`No index.json at ${indexPath}`);
|
|
4171
4532
|
return 0;
|
|
4172
4533
|
}
|
|
4173
4534
|
let index;
|
|
4174
4535
|
try {
|
|
4175
|
-
index = JSON.parse(
|
|
4536
|
+
index = JSON.parse(readFileSync13(indexPath, "utf-8"));
|
|
4176
4537
|
} catch (err) {
|
|
4177
4538
|
console.error(`[ProfileLoader] Failed to parse ${indexPath}:`, err);
|
|
4178
4539
|
return 0;
|
|
4179
4540
|
}
|
|
4180
4541
|
let loaded = 0;
|
|
4181
4542
|
for (const [profileId, relativePath] of Object.entries(index.profiles)) {
|
|
4182
|
-
const profilePath =
|
|
4543
|
+
const profilePath = join13(dir, relativePath);
|
|
4183
4544
|
try {
|
|
4184
|
-
const profile = JSON.parse(
|
|
4545
|
+
const profile = JSON.parse(readFileSync13(profilePath, "utf-8"));
|
|
4185
4546
|
registerProfile(profileId, profile);
|
|
4186
4547
|
const shortName = profileId.split("/").pop()?.replace(/@.*$/, "");
|
|
4187
4548
|
if (shortName && shortName !== profileId) {
|
|
@@ -4217,8 +4578,8 @@ function warnNoProfiles(reason) {
|
|
|
4217
4578
|
import { decodeAttestationBlob as decodeAttestationBlob3 } from "@hap/core";
|
|
4218
4579
|
|
|
4219
4580
|
// src/lib/committed-executor.ts
|
|
4220
|
-
import { existsSync as
|
|
4221
|
-
import { dirname as
|
|
4581
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync14, unlinkSync as unlinkSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
4582
|
+
import { dirname as dirname9, join as join14 } from "path";
|
|
4222
4583
|
var CommittedExecutor = class {
|
|
4223
4584
|
constructor(run) {
|
|
4224
4585
|
this.run = run;
|
|
@@ -4245,8 +4606,8 @@ var CommittedExecutor = class {
|
|
|
4245
4606
|
var ExecutorLock = class {
|
|
4246
4607
|
path;
|
|
4247
4608
|
held = false;
|
|
4248
|
-
constructor(
|
|
4249
|
-
this.path =
|
|
4609
|
+
constructor(dataDir2) {
|
|
4610
|
+
this.path = join14(dataDir2, "executor.lock");
|
|
4250
4611
|
}
|
|
4251
4612
|
/** Try to take the lock. Returns the holder's pid when someone else has it. */
|
|
4252
4613
|
acquire() {
|
|
@@ -4254,9 +4615,9 @@ var ExecutorLock = class {
|
|
|
4254
4615
|
if (current && current.pid !== process.pid && isAlive(current.pid)) {
|
|
4255
4616
|
return { held: false, holderPid: current.pid };
|
|
4256
4617
|
}
|
|
4257
|
-
|
|
4618
|
+
mkdirSync10(dirname9(this.path), { recursive: true, mode: 448 });
|
|
4258
4619
|
const lock = { pid: process.pid, startedAt: Math.floor(Date.now() / 1e3) };
|
|
4259
|
-
|
|
4620
|
+
writeFileSync10(this.path, JSON.stringify(lock), { mode: 384 });
|
|
4260
4621
|
this.held = true;
|
|
4261
4622
|
return { held: true };
|
|
4262
4623
|
}
|
|
@@ -4272,15 +4633,15 @@ var ExecutorLock = class {
|
|
|
4272
4633
|
const current = this.read();
|
|
4273
4634
|
if (current?.pid === process.pid) {
|
|
4274
4635
|
try {
|
|
4275
|
-
|
|
4636
|
+
unlinkSync6(this.path);
|
|
4276
4637
|
} catch {
|
|
4277
4638
|
}
|
|
4278
4639
|
}
|
|
4279
4640
|
}
|
|
4280
4641
|
read() {
|
|
4281
|
-
if (!
|
|
4642
|
+
if (!existsSync14(this.path)) return null;
|
|
4282
4643
|
try {
|
|
4283
|
-
const parsed = JSON.parse(
|
|
4644
|
+
const parsed = JSON.parse(readFileSync14(this.path, "utf8"));
|
|
4284
4645
|
return typeof parsed?.pid === "number" ? parsed : null;
|
|
4285
4646
|
} catch {
|
|
4286
4647
|
return null;
|
|
@@ -4297,11 +4658,115 @@ function isAlive(pid) {
|
|
|
4297
4658
|
}
|
|
4298
4659
|
|
|
4299
4660
|
// bin/http.ts
|
|
4300
|
-
import { homedir as
|
|
4301
|
-
import { join as
|
|
4302
|
-
|
|
4661
|
+
import { homedir as homedir10 } from "os";
|
|
4662
|
+
import { join as join17 } from "path";
|
|
4663
|
+
|
|
4664
|
+
// src/lib/as-config.ts
|
|
4665
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "fs";
|
|
4666
|
+
import { dirname as dirname10, join as join15 } from "path";
|
|
4667
|
+
var DEFAULT_AS_URL = "https://www.suveren.ai";
|
|
4668
|
+
function configPath(dataDir2) {
|
|
4669
|
+
return join15(dataDir2, "config.json");
|
|
4670
|
+
}
|
|
4671
|
+
function readAsConfigStrict(dataDir2) {
|
|
4672
|
+
const path = configPath(dataDir2);
|
|
4673
|
+
if (!existsSync15(path)) return {};
|
|
4674
|
+
let data;
|
|
4675
|
+
try {
|
|
4676
|
+
data = JSON.parse(readFileSync15(path, "utf-8"));
|
|
4677
|
+
} catch (err) {
|
|
4678
|
+
throw new Error(
|
|
4679
|
+
`Could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
4680
|
+
);
|
|
4681
|
+
}
|
|
4682
|
+
const out = {};
|
|
4683
|
+
if (typeof data.asUrl === "string") out.asUrl = data.asUrl;
|
|
4684
|
+
if (typeof data.caFile === "string") out.caFile = data.caFile;
|
|
4685
|
+
return out;
|
|
4686
|
+
}
|
|
4687
|
+
function validateAsUrl(candidate) {
|
|
4688
|
+
const trimmed = candidate.trim();
|
|
4689
|
+
if (!trimmed) return { ok: false, error: "The Authority Server URL is empty." };
|
|
4690
|
+
let parsed;
|
|
4691
|
+
try {
|
|
4692
|
+
parsed = new URL(trimmed);
|
|
4693
|
+
} catch {
|
|
4694
|
+
return { ok: false, error: `"${trimmed}" is not a valid URL.` };
|
|
4695
|
+
}
|
|
4696
|
+
const isLocalHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
4697
|
+
if (parsed.protocol !== "https:" && !isLocalHttp) {
|
|
4698
|
+
return {
|
|
4699
|
+
ok: false,
|
|
4700
|
+
error: `"${trimmed}" must use https:// (http:// is only allowed for http://localhost or http://127.0.0.1).`
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
let normalized = `${parsed.origin}${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
4704
|
+
if (normalized.endsWith("/") && normalized !== `${parsed.origin}/`) {
|
|
4705
|
+
normalized = normalized.slice(0, -1);
|
|
4706
|
+
} else if (normalized === `${parsed.origin}/`) {
|
|
4707
|
+
normalized = parsed.origin;
|
|
4708
|
+
}
|
|
4709
|
+
return { ok: true, url: normalized };
|
|
4710
|
+
}
|
|
4711
|
+
function resolveAsUrl(dataDir2, flag) {
|
|
4712
|
+
if (flag) {
|
|
4713
|
+
const v = validateAsUrl(flag);
|
|
4714
|
+
if (!v.ok) throw new Error(`Invalid --as-url: ${v.error}`);
|
|
4715
|
+
return v.url;
|
|
4716
|
+
}
|
|
4717
|
+
const envUrl = process.env.SUVEREN_AS_URL;
|
|
4718
|
+
if (envUrl) {
|
|
4719
|
+
const v = validateAsUrl(envUrl);
|
|
4720
|
+
if (!v.ok) throw new Error(`Invalid SUVEREN_AS_URL: ${v.error}`);
|
|
4721
|
+
return v.url;
|
|
4722
|
+
}
|
|
4723
|
+
const saved = readAsConfigStrict(dataDir2).asUrl;
|
|
4724
|
+
if (saved) {
|
|
4725
|
+
const v = validateAsUrl(saved);
|
|
4726
|
+
if (!v.ok) throw new Error(`Invalid saved as-url "${saved}" in ${dataDir2}/config.json: ${v.error}`);
|
|
4727
|
+
return v.url;
|
|
4728
|
+
}
|
|
4729
|
+
return DEFAULT_AS_URL;
|
|
4730
|
+
}
|
|
4731
|
+
|
|
4732
|
+
// src/lib/mcp-as-tracker.ts
|
|
4733
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
|
|
4734
|
+
import { dirname as dirname11, join as join16 } from "path";
|
|
4735
|
+
function trackerPath(dataDir2) {
|
|
4736
|
+
return join16(dataDir2, "mcp-as-pairing.json");
|
|
4737
|
+
}
|
|
4738
|
+
function readMcpPairedAsUrl(dataDir2) {
|
|
4739
|
+
const path = trackerPath(dataDir2);
|
|
4740
|
+
if (!existsSync16(path)) return null;
|
|
4741
|
+
try {
|
|
4742
|
+
const data = JSON.parse(readFileSync16(path, "utf-8"));
|
|
4743
|
+
return typeof data.asUrl === "string" ? data.asUrl : null;
|
|
4744
|
+
} catch {
|
|
4745
|
+
return null;
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
function writeMcpPairedAsUrl(dataDir2, asUrl) {
|
|
4749
|
+
const path = trackerPath(dataDir2);
|
|
4750
|
+
mkdirSync12(dirname11(path), { recursive: true, mode: 448 });
|
|
4751
|
+
writeFileSync12(path, JSON.stringify({ asUrl }, null, 2), { encoding: "utf-8", mode: 384 });
|
|
4752
|
+
}
|
|
4753
|
+
|
|
4754
|
+
// bin/http.ts
|
|
4755
|
+
var dataDir = process.env.SUVEREN_DATA_DIR ?? join17(homedir10(), ".suveren");
|
|
4756
|
+
var spUrl = resolveAsUrl(dataDir);
|
|
4303
4757
|
var port = parseInt(process.env.SUVEREN_MCP_PORT ?? "3430", 10);
|
|
4304
|
-
|
|
4758
|
+
setAsBaseUrl(spUrl);
|
|
4759
|
+
var state = new SharedState(spUrl, void 0, dataDir);
|
|
4760
|
+
(function repairIfAsUrlChanged() {
|
|
4761
|
+
const lastKnown = readMcpPairedAsUrl(dataDir);
|
|
4762
|
+
if (lastKnown !== null && lastKnown !== spUrl) {
|
|
4763
|
+
console.error(
|
|
4764
|
+
`[Suveren MCP] Authority Server changed (${lastKnown} \u2192 ${spUrl}) \u2014 clearing cached mandates. Sign in again to re-pair.`
|
|
4765
|
+
);
|
|
4766
|
+
state.gateStore.clearAll();
|
|
4767
|
+
}
|
|
4768
|
+
writeMcpPairedAsUrl(dataDir, spUrl);
|
|
4769
|
+
})();
|
|
4305
4770
|
var spApiKey = process.env.SUVEREN_AS_API_KEY ?? "";
|
|
4306
4771
|
if (spApiKey) {
|
|
4307
4772
|
state.spClient.setApiKey(spApiKey);
|
|
@@ -4371,9 +4836,11 @@ app.post("/internal/configure", internalOnly, (req, res) => {
|
|
|
4371
4836
|
}
|
|
4372
4837
|
res.json({ ok: true });
|
|
4373
4838
|
});
|
|
4374
|
-
app.post("/internal/clear-session", internalOnly, (
|
|
4375
|
-
|
|
4376
|
-
|
|
4839
|
+
app.post("/internal/clear-session", internalOnly, (req, res) => {
|
|
4840
|
+
const reason = req.body?.reason;
|
|
4841
|
+
const validReason = reason === "as-key-mismatch" || reason === "as-url-changed" ? reason : void 0;
|
|
4842
|
+
state.spClient.clearSession(validReason);
|
|
4843
|
+
console.error(`[Suveren MCP] Session cleared by control-plane (${validReason ?? "expired"})`);
|
|
4377
4844
|
res.json({ ok: true });
|
|
4378
4845
|
});
|
|
4379
4846
|
app.post("/internal/gate-content", internalOnly, async (req, res) => {
|
|
@@ -4665,6 +5132,15 @@ app.get("/internal/authorizations", internalOnly, (_req, res) => {
|
|
|
4665
5132
|
app.get("/internal/manifests", internalOnly, (_req, res) => {
|
|
4666
5133
|
res.json({ manifests: getAllManifests() });
|
|
4667
5134
|
});
|
|
5135
|
+
app.get("/internal/skipped-commitments", internalOnly, async (_req, res) => {
|
|
5136
|
+
try {
|
|
5137
|
+
const committed = await state.spClient.getCommittedProposals();
|
|
5138
|
+
const skipped = committed.filter((p) => !state.proposalSubmissions.get(p.id)).map((p) => ({ id: p.id, tool: p.tool, note: buildSkippedProposalNote(p.id) }));
|
|
5139
|
+
res.json({ skipped });
|
|
5140
|
+
} catch (err) {
|
|
5141
|
+
res.status(502).json({ error: err instanceof Error ? err.message : "Could not reach the Authority Server" });
|
|
5142
|
+
}
|
|
5143
|
+
});
|
|
4668
5144
|
app.get("/internal/evidence", internalOnly, (_req, res) => {
|
|
4669
5145
|
if (state.receiptArchive.isLocked()) {
|
|
4670
5146
|
res.status(503).json({ error: "Vault locked \u2014 the evidence archive is encrypted until sign-in." });
|
|
@@ -4798,12 +5274,12 @@ app.listen(port, "0.0.0.0", () => {
|
|
|
4798
5274
|
(proposal) => executeCommitted(proposal, state, integrationManager)
|
|
4799
5275
|
);
|
|
4800
5276
|
installCommittedExecutor(committedExecutor);
|
|
4801
|
-
const
|
|
4802
|
-
const executorLock = new ExecutorLock(
|
|
5277
|
+
const dataDir2 = process.env.SUVEREN_DATA_DIR ?? join17(homedir10(), ".suveren");
|
|
5278
|
+
const executorLock = new ExecutorLock(dataDir2);
|
|
4803
5279
|
const lock = executorLock.acquire();
|
|
4804
5280
|
if (!lock.held) {
|
|
4805
5281
|
console.error(
|
|
4806
|
-
`[Suveren MCP] Committed-proposal execution is DISABLED in this process: pid ${lock.holderPid} holds ${
|
|
5282
|
+
`[Suveren MCP] Committed-proposal execution is DISABLED in this process: pid ${lock.holderPid} holds ${dataDir2}/executor.lock. Approved proposals will run there. Stop that gateway if this one should execute.`
|
|
4807
5283
|
);
|
|
4808
5284
|
}
|
|
4809
5285
|
for (const sig of ["SIGINT", "SIGTERM", "exit"]) {
|