@suveren/gateway 0.8.6 → 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.
Files changed (670) hide show
  1. package/bin/suveren-gateway.js +165 -9
  2. package/dist/control-plane/index.mjs +546 -87
  3. package/dist/mcp-server/http.mjs +727 -187
  4. package/dist/ui/assets/index-CIiOCgjJ.js +110 -0
  5. package/dist/ui/icons/apple-touch-icon.png +0 -0
  6. package/dist/ui/icons/icon-192.png +0 -0
  7. package/dist/ui/icons/icon-512.png +0 -0
  8. package/dist/ui/icons/icon-maskable-512.png +0 -0
  9. package/dist/ui/index.html +7 -1
  10. package/dist/ui/manifest.webmanifest +15 -0
  11. package/lib/config.d.mts +37 -0
  12. package/lib/config.mjs +150 -0
  13. package/node_modules/@hap/core/dist/index.d.mts +33 -2
  14. package/node_modules/@hap/core/dist/index.d.ts +33 -2
  15. package/node_modules/@hap/core/dist/index.js +26 -2
  16. package/node_modules/@hap/core/dist/index.mjs +25 -2
  17. package/node_modules/@hap/core/package.json +1 -1
  18. package/node_modules/@hap/core/src/gatekeeper.ts +36 -2
  19. package/node_modules/@hap/core/src/types.ts +21 -1
  20. package/node_modules/@hono/node-server/README.md +21 -10
  21. package/node_modules/@hono/node-server/dist/early-hints.cjs +1 -1
  22. package/node_modules/@hono/node-server/dist/early-hints.mjs +1 -1
  23. package/node_modules/@hono/node-server/dist/index.cjs +41 -19
  24. package/node_modules/@hono/node-server/dist/index.mjs +42 -20
  25. package/node_modules/@hono/node-server/dist/serve-static.cjs +1 -0
  26. package/node_modules/@hono/node-server/dist/serve-static.d.cts +2 -1
  27. package/node_modules/@hono/node-server/dist/serve-static.d.mts +2 -1
  28. package/node_modules/@hono/node-server/dist/serve-static.mjs +1 -0
  29. package/node_modules/@hono/node-server/package.json +3 -2
  30. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.d.ts +43 -2
  31. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.d.ts.map +1 -1
  32. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.js +26 -5
  33. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth-extensions.js.map +1 -1
  34. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts +26 -4
  35. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.d.ts.map +1 -1
  36. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js +118 -17
  37. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/auth.js.map +1 -1
  38. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.d.ts +1 -0
  39. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.d.ts.map +1 -1
  40. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.js +11 -2
  41. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/client/simpleClientCredentials.js.map +1 -1
  42. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts +2 -0
  43. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/examples/server/demoInMemoryOAuthProvider.d.ts.map +1 -1
  44. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.d.ts.map +1 -1
  45. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.js +6 -3
  46. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/auth/providers/proxyProvider.js.map +1 -1
  47. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.d.ts.map +1 -1
  48. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.js +3 -1
  49. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/express.js.map +1 -1
  50. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.d.ts +25 -0
  51. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.d.ts.map +1 -0
  52. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.js +64 -0
  53. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/requestBody.js.map +1 -0
  54. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts +10 -1
  55. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts.map +1 -1
  56. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js +13 -1
  57. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js.map +1 -1
  58. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.d.ts +3 -0
  59. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.d.ts.map +1 -1
  60. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js +12 -2
  61. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/auth.js.map +1 -1
  62. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.d.ts +43 -2
  63. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.d.ts.map +1 -1
  64. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.js +26 -5
  65. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth-extensions.js.map +1 -1
  66. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts +26 -4
  67. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.d.ts.map +1 -1
  68. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js +118 -17
  69. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js.map +1 -1
  70. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.d.ts +1 -0
  71. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.d.ts.map +1 -1
  72. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.js +11 -2
  73. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/client/simpleClientCredentials.js.map +1 -1
  74. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/server/demoInMemoryOAuthProvider.d.ts +2 -0
  75. package/node_modules/@modelcontextprotocol/sdk/dist/esm/examples/server/demoInMemoryOAuthProvider.d.ts.map +1 -1
  76. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.d.ts.map +1 -1
  77. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.js +6 -3
  78. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/providers/proxyProvider.js.map +1 -1
  79. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.d.ts.map +1 -1
  80. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.js +3 -1
  81. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.js.map +1 -1
  82. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.d.ts +25 -0
  83. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.d.ts.map +1 -0
  84. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js +58 -0
  85. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/requestBody.js.map +1 -0
  86. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts +10 -1
  87. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts.map +1 -1
  88. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js +13 -1
  89. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js.map +1 -1
  90. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.d.ts +3 -0
  91. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.d.ts.map +1 -1
  92. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js +12 -2
  93. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js.map +1 -1
  94. package/node_modules/@modelcontextprotocol/sdk/package.json +1 -1
  95. package/node_modules/@types/node/README.md +1 -1
  96. package/node_modules/@types/node/crypto.d.ts +2 -2
  97. package/node_modules/@types/node/dgram.d.ts +1 -1
  98. package/node_modules/@types/node/package.json +2 -2
  99. package/node_modules/hono/dist/_virtual/_rolldown/runtime.js +13 -0
  100. package/node_modules/hono/dist/adapter/aws-lambda/conninfo.js +42 -23
  101. package/node_modules/hono/dist/adapter/aws-lambda/handler.js +318 -341
  102. package/node_modules/hono/dist/adapter/aws-lambda/index.js +2 -8
  103. package/node_modules/hono/dist/adapter/aws-lambda/types.js +1 -0
  104. package/node_modules/hono/dist/adapter/bun/conninfo.js +20 -25
  105. package/node_modules/hono/dist/adapter/bun/index.js +3 -13
  106. package/node_modules/hono/dist/adapter/bun/serve-static.js +27 -27
  107. package/node_modules/hono/dist/adapter/bun/server.js +11 -5
  108. package/node_modules/hono/dist/adapter/bun/ssg.js +25 -15
  109. package/node_modules/hono/dist/adapter/bun/websocket.js +61 -68
  110. package/node_modules/hono/dist/adapter/cloudflare-pages/conninfo.js +24 -9
  111. package/node_modules/hono/dist/adapter/cloudflare-pages/handler.js +59 -62
  112. package/node_modules/hono/dist/adapter/cloudflare-pages/index.js +2 -8
  113. package/node_modules/hono/dist/adapter/cloudflare-workers/conninfo.js +7 -9
  114. package/node_modules/hono/dist/adapter/cloudflare-workers/index.js +3 -8
  115. package/node_modules/hono/dist/adapter/cloudflare-workers/serve-static-module.js +5 -6
  116. package/node_modules/hono/dist/adapter/cloudflare-workers/serve-static.js +26 -20
  117. package/node_modules/hono/dist/adapter/cloudflare-workers/utils.js +21 -34
  118. package/node_modules/hono/dist/adapter/cloudflare-workers/websocket.js +31 -39
  119. package/node_modules/hono/dist/adapter/deno/conninfo.js +16 -13
  120. package/node_modules/hono/dist/adapter/deno/deno.d.js +1 -0
  121. package/node_modules/hono/dist/adapter/deno/index.js +3 -10
  122. package/node_modules/hono/dist/adapter/deno/serve-static.js +33 -38
  123. package/node_modules/hono/dist/adapter/deno/ssg.js +27 -16
  124. package/node_modules/hono/dist/adapter/deno/websocket.js +30 -30
  125. package/node_modules/hono/dist/adapter/lambda-edge/conninfo.js +7 -9
  126. package/node_modules/hono/dist/adapter/lambda-edge/handler.js +102 -87
  127. package/node_modules/hono/dist/adapter/lambda-edge/index.js +2 -6
  128. package/node_modules/hono/dist/adapter/netlify/conninfo.js +24 -9
  129. package/node_modules/hono/dist/adapter/netlify/handler.js +10 -8
  130. package/node_modules/hono/dist/adapter/netlify/index.js +3 -2
  131. package/node_modules/hono/dist/adapter/netlify/mod.js +2 -6
  132. package/node_modules/hono/dist/adapter/service-worker/handler.js +15 -19
  133. package/node_modules/hono/dist/adapter/service-worker/index.js +23 -7
  134. package/node_modules/hono/dist/adapter/service-worker/types.js +1 -0
  135. package/node_modules/hono/dist/adapter/vercel/conninfo.js +7 -10
  136. package/node_modules/hono/dist/adapter/vercel/handler.js +8 -6
  137. package/node_modules/hono/dist/adapter/vercel/index.js +2 -6
  138. package/node_modules/hono/dist/cjs/_virtual/_rolldown/runtime.js +33 -0
  139. package/node_modules/hono/dist/cjs/adapter/aws-lambda/conninfo.js +42 -44
  140. package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +326 -370
  141. package/node_modules/hono/dist/cjs/adapter/aws-lambda/index.js +7 -34
  142. package/node_modules/hono/dist/cjs/adapter/aws-lambda/types.js +0 -15
  143. package/node_modules/hono/dist/cjs/adapter/bun/conninfo.js +21 -47
  144. package/node_modules/hono/dist/cjs/adapter/bun/index.js +14 -45
  145. package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +29 -50
  146. package/node_modules/hono/dist/cjs/adapter/bun/server.js +11 -26
  147. package/node_modules/hono/dist/cjs/adapter/bun/ssg.js +24 -35
  148. package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +63 -91
  149. package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/conninfo.js +25 -31
  150. package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/handler.js +61 -85
  151. package/node_modules/hono/dist/cjs/adapter/cloudflare-pages/index.js +7 -34
  152. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/conninfo.js +8 -31
  153. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/index.js +7 -33
  154. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/serve-static-module.js +7 -29
  155. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/serve-static.js +27 -42
  156. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/utils.js +21 -55
  157. package/node_modules/hono/dist/cjs/adapter/cloudflare-workers/websocket.js +33 -62
  158. package/node_modules/hono/dist/cjs/adapter/deno/conninfo.js +16 -34
  159. package/node_modules/hono/dist/cjs/adapter/deno/index.js +10 -38
  160. package/node_modules/hono/dist/cjs/adapter/deno/serve-static.js +33 -59
  161. package/node_modules/hono/dist/cjs/adapter/deno/ssg.js +27 -37
  162. package/node_modules/hono/dist/cjs/adapter/deno/websocket.js +32 -53
  163. package/node_modules/hono/dist/cjs/adapter/lambda-edge/conninfo.js +8 -31
  164. package/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +105 -119
  165. package/node_modules/hono/dist/cjs/adapter/lambda-edge/index.js +5 -30
  166. package/node_modules/hono/dist/cjs/adapter/netlify/conninfo.js +25 -31
  167. package/node_modules/hono/dist/cjs/adapter/netlify/handler.js +10 -29
  168. package/node_modules/hono/dist/cjs/adapter/netlify/index.js +5 -21
  169. package/node_modules/hono/dist/cjs/adapter/netlify/mod.js +5 -30
  170. package/node_modules/hono/dist/cjs/adapter/service-worker/handler.js +16 -41
  171. package/node_modules/hono/dist/cjs/adapter/service-worker/index.js +25 -30
  172. package/node_modules/hono/dist/cjs/adapter/service-worker/types.js +0 -15
  173. package/node_modules/hono/dist/cjs/adapter/vercel/conninfo.js +8 -32
  174. package/node_modules/hono/dist/cjs/adapter/vercel/handler.js +8 -27
  175. package/node_modules/hono/dist/cjs/adapter/vercel/index.js +5 -30
  176. package/node_modules/hono/dist/cjs/client/client.js +139 -212
  177. package/node_modules/hono/dist/cjs/client/fetch-result-please.js +62 -80
  178. package/node_modules/hono/dist/cjs/client/index.js +7 -32
  179. package/node_modules/hono/dist/cjs/client/types.js +0 -15
  180. package/node_modules/hono/dist/cjs/client/utils.js +54 -92
  181. package/node_modules/hono/dist/cjs/compose.js +49 -66
  182. package/node_modules/hono/dist/cjs/context.js +379 -450
  183. package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +47 -70
  184. package/node_modules/hono/dist/cjs/helper/accepts/index.js +3 -27
  185. package/node_modules/hono/dist/cjs/helper/adapter/index.js +33 -73
  186. package/node_modules/hono/dist/cjs/helper/conninfo/index.js +0 -15
  187. package/node_modules/hono/dist/cjs/helper/conninfo/types.js +0 -15
  188. package/node_modules/hono/dist/cjs/helper/cookie/index.js +75 -116
  189. package/node_modules/hono/dist/cjs/helper/css/common.js +165 -244
  190. package/node_modules/hono/dist/cjs/helper/css/index.js +136 -151
  191. package/node_modules/hono/dist/cjs/helper/dev/index.js +45 -71
  192. package/node_modules/hono/dist/cjs/helper/factory/index.js +30 -51
  193. package/node_modules/hono/dist/cjs/helper/html/index.js +32 -62
  194. package/node_modules/hono/dist/cjs/helper/proxy/index.js +113 -106
  195. package/node_modules/hono/dist/cjs/helper/route/index.js +123 -66
  196. package/node_modules/hono/dist/cjs/helper/ssg/index.js +19 -43
  197. package/node_modules/hono/dist/cjs/helper/ssg/middleware.js +56 -64
  198. package/node_modules/hono/dist/cjs/helper/ssg/plugins.js +55 -57
  199. package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +196 -296
  200. package/node_modules/hono/dist/cjs/helper/ssg/utils.js +47 -90
  201. package/node_modules/hono/dist/cjs/helper/streaming/index.js +8 -35
  202. package/node_modules/hono/dist/cjs/helper/streaming/sse.js +53 -85
  203. package/node_modules/hono/dist/cjs/helper/streaming/stream.js +23 -53
  204. package/node_modules/hono/dist/cjs/helper/streaming/text.js +10 -32
  205. package/node_modules/hono/dist/cjs/helper/streaming/utils.js +13 -32
  206. package/node_modules/hono/dist/cjs/helper/testing/index.js +16 -31
  207. package/node_modules/hono/dist/cjs/helper/websocket/index.js +51 -76
  208. package/node_modules/hono/dist/cjs/hono-base.js +345 -403
  209. package/node_modules/hono/dist/cjs/hono.js +28 -42
  210. package/node_modules/hono/dist/cjs/http-exception.js +55 -56
  211. package/node_modules/hono/dist/cjs/index.js +22 -30
  212. package/node_modules/hono/dist/cjs/jsx/base.js +237 -366
  213. package/node_modules/hono/dist/cjs/jsx/children.js +16 -41
  214. package/node_modules/hono/dist/cjs/jsx/components.js +119 -192
  215. package/node_modules/hono/dist/cjs/jsx/constants.js +15 -42
  216. package/node_modules/hono/dist/cjs/jsx/context.js +144 -162
  217. package/node_modules/hono/dist/cjs/jsx/dom/client.js +49 -69
  218. package/node_modules/hono/dist/cjs/jsx/dom/components.js +23 -52
  219. package/node_modules/hono/dist/cjs/jsx/dom/context.js +39 -67
  220. package/node_modules/hono/dist/cjs/jsx/dom/css.js +143 -158
  221. package/node_modules/hono/dist/cjs/jsx/dom/hooks/index.js +55 -64
  222. package/node_modules/hono/dist/cjs/jsx/dom/index.js +114 -173
  223. package/node_modules/hono/dist/cjs/jsx/dom/intrinsic-element/components.js +282 -375
  224. package/node_modules/hono/dist/cjs/jsx/dom/jsx-dev-runtime.js +14 -49
  225. package/node_modules/hono/dist/cjs/jsx/dom/jsx-runtime.js +5 -32
  226. package/node_modules/hono/dist/cjs/jsx/dom/render.js +469 -623
  227. package/node_modules/hono/dist/cjs/jsx/dom/server.js +37 -64
  228. package/node_modules/hono/dist/cjs/jsx/dom/utils.js +7 -30
  229. package/node_modules/hono/dist/cjs/jsx/hooks/index.js +225 -318
  230. package/node_modules/hono/dist/cjs/jsx/index.js +86 -135
  231. package/node_modules/hono/dist/cjs/jsx/intrinsic-element/common.js +20 -43
  232. package/node_modules/hono/dist/cjs/jsx/intrinsic-element/components.js +117 -168
  233. package/node_modules/hono/dist/cjs/jsx/intrinsic-elements.js +0 -15
  234. package/node_modules/hono/dist/cjs/jsx/jsx-dev-runtime.js +14 -39
  235. package/node_modules/hono/dist/cjs/jsx/jsx-runtime.js +34 -68
  236. package/node_modules/hono/dist/cjs/jsx/streaming.js +123 -166
  237. package/node_modules/hono/dist/cjs/jsx/types.js +0 -15
  238. package/node_modules/hono/dist/cjs/jsx/utils.js +91 -175
  239. package/node_modules/hono/dist/cjs/middleware/basic-auth/index.js +98 -86
  240. package/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +92 -109
  241. package/node_modules/hono/dist/cjs/middleware/body-limit/index.js +66 -72
  242. package/node_modules/hono/dist/cjs/middleware/cache/index.js +153 -199
  243. package/node_modules/hono/dist/cjs/middleware/combine/index.js +135 -95
  244. package/node_modules/hono/dist/cjs/middleware/compress/index.js +73 -88
  245. package/node_modules/hono/dist/cjs/middleware/context-storage/index.js +49 -41
  246. package/node_modules/hono/dist/cjs/middleware/cors/index.js +107 -107
  247. package/node_modules/hono/dist/cjs/middleware/csrf/index.js +101 -72
  248. package/node_modules/hono/dist/cjs/middleware/etag/digest.js +58 -97
  249. package/node_modules/hono/dist/cjs/middleware/etag/index.js +71 -91
  250. package/node_modules/hono/dist/cjs/middleware/ip-restriction/index.js +161 -169
  251. package/node_modules/hono/dist/cjs/middleware/jsx-renderer/index.js +99 -77
  252. package/node_modules/hono/dist/cjs/middleware/jwk/index.js +3 -27
  253. package/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +118 -135
  254. package/node_modules/hono/dist/cjs/middleware/jwt/index.js +9 -38
  255. package/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +120 -141
  256. package/node_modules/hono/dist/cjs/middleware/language/index.js +7 -35
  257. package/node_modules/hono/dist/cjs/middleware/language/language.js +184 -182
  258. package/node_modules/hono/dist/cjs/middleware/logger/index.js +41 -62
  259. package/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +82 -88
  260. package/node_modules/hono/dist/cjs/middleware/method-override/index.js +101 -102
  261. package/node_modules/hono/dist/cjs/middleware/powered-by/index.js +23 -30
  262. package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +38 -36
  263. package/node_modules/hono/dist/cjs/middleware/request-id/index.js +3 -27
  264. package/node_modules/hono/dist/cjs/middleware/request-id/request-id.js +34 -42
  265. package/node_modules/hono/dist/cjs/middleware/secure-headers/index.js +4 -29
  266. package/node_modules/hono/dist/cjs/middleware/secure-headers/permissions-policy.js +0 -15
  267. package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +142 -174
  268. package/node_modules/hono/dist/cjs/middleware/serve-static/index.js +56 -93
  269. package/node_modules/hono/dist/cjs/middleware/serve-static/path.js +15 -38
  270. package/node_modules/hono/dist/cjs/middleware/timeout/index.js +40 -45
  271. package/node_modules/hono/dist/cjs/middleware/timing/index.js +7 -35
  272. package/node_modules/hono/dist/cjs/middleware/timing/timing.js +177 -118
  273. package/node_modules/hono/dist/cjs/middleware/trailing-slash/index.js +85 -58
  274. package/node_modules/hono/dist/cjs/preset/quick.js +18 -37
  275. package/node_modules/hono/dist/cjs/preset/tiny.js +15 -33
  276. package/node_modules/hono/dist/cjs/request/constants.js +5 -27
  277. package/node_modules/hono/dist/cjs/request.js +334 -346
  278. package/node_modules/hono/dist/cjs/router/linear-router/index.js +3 -27
  279. package/node_modules/hono/dist/cjs/router/linear-router/router.js +95 -143
  280. package/node_modules/hono/dist/cjs/router/pattern-router/index.js +3 -27
  281. package/node_modules/hono/dist/cjs/router/pattern-router/router.js +41 -63
  282. package/node_modules/hono/dist/cjs/router/reg-exp-router/index.js +7 -34
  283. package/node_modules/hono/dist/cjs/router/reg-exp-router/matcher.js +18 -45
  284. package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +91 -135
  285. package/node_modules/hono/dist/cjs/router/reg-exp-router/prepared-router.js +92 -161
  286. package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +98 -147
  287. package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +73 -89
  288. package/node_modules/hono/dist/cjs/router/smart-router/index.js +3 -27
  289. package/node_modules/hono/dist/cjs/router/smart-router/router.js +49 -79
  290. package/node_modules/hono/dist/cjs/router/trie-router/index.js +3 -27
  291. package/node_modules/hono/dist/cjs/router/trie-router/node.js +134 -186
  292. package/node_modules/hono/dist/cjs/router/trie-router/router.js +15 -39
  293. package/node_modules/hono/dist/cjs/router/utils.js +5 -27
  294. package/node_modules/hono/dist/cjs/router.js +37 -37
  295. package/node_modules/hono/dist/cjs/types.js +5 -28
  296. package/node_modules/hono/dist/cjs/utils/accept.js +177 -225
  297. package/node_modules/hono/dist/cjs/utils/basic-auth.js +16 -40
  298. package/node_modules/hono/dist/cjs/utils/body.js +84 -110
  299. package/node_modules/hono/dist/cjs/utils/buffer.js +43 -91
  300. package/node_modules/hono/dist/cjs/utils/color.js +35 -44
  301. package/node_modules/hono/dist/cjs/utils/compress.js +11 -26
  302. package/node_modules/hono/dist/cjs/utils/concurrent.js +29 -59
  303. package/node_modules/hono/dist/cjs/utils/constants.js +7 -26
  304. package/node_modules/hono/dist/cjs/utils/cookie.js +107 -177
  305. package/node_modules/hono/dist/cjs/utils/crypto.js +30 -61
  306. package/node_modules/hono/dist/cjs/utils/encode.js +31 -48
  307. package/node_modules/hono/dist/cjs/utils/filepath.js +23 -54
  308. package/node_modules/hono/dist/cjs/utils/handler.js +11 -33
  309. package/node_modules/hono/dist/cjs/utils/headers.js +0 -15
  310. package/node_modules/hono/dist/cjs/utils/html.js +96 -137
  311. package/node_modules/hono/dist/cjs/utils/http-status.js +0 -15
  312. package/node_modules/hono/dist/cjs/utils/ipaddr.js +213 -286
  313. package/node_modules/hono/dist/cjs/utils/jwt/index.js +14 -27
  314. package/node_modules/hono/dist/cjs/utils/jwt/jwa.js +25 -42
  315. package/node_modules/hono/dist/cjs/utils/jwt/jws.js +119 -199
  316. package/node_modules/hono/dist/cjs/utils/jwt/jwt.js +122 -205
  317. package/node_modules/hono/dist/cjs/utils/jwt/types.js +122 -159
  318. package/node_modules/hono/dist/cjs/utils/jwt/utf8.js +9 -28
  319. package/node_modules/hono/dist/cjs/utils/mime.js +75 -101
  320. package/node_modules/hono/dist/cjs/utils/stream.js +88 -111
  321. package/node_modules/hono/dist/cjs/utils/types.js +0 -15
  322. package/node_modules/hono/dist/cjs/utils/url.js +185 -234
  323. package/node_modules/hono/dist/cjs/validator/index.js +3 -27
  324. package/node_modules/hono/dist/cjs/validator/utils.js +0 -15
  325. package/node_modules/hono/dist/cjs/validator/validator.js +60 -103
  326. package/node_modules/hono/dist/client/client.js +138 -197
  327. package/node_modules/hono/dist/client/fetch-result-please.js +59 -56
  328. package/node_modules/hono/dist/client/index.js +3 -7
  329. package/node_modules/hono/dist/client/types.js +1 -0
  330. package/node_modules/hono/dist/client/utils.js +51 -68
  331. package/node_modules/hono/dist/compose.js +49 -45
  332. package/node_modules/hono/dist/context.js +376 -426
  333. package/node_modules/hono/dist/helper/accepts/accepts.js +47 -49
  334. package/node_modules/hono/dist/helper/accepts/index.js +1 -4
  335. package/node_modules/hono/dist/helper/adapter/index.js +33 -52
  336. package/node_modules/hono/dist/helper/conninfo/index.js +1 -0
  337. package/node_modules/hono/dist/helper/conninfo/types.js +1 -0
  338. package/node_modules/hono/dist/helper/cookie/index.js +74 -94
  339. package/node_modules/hono/dist/helper/css/common.js +167 -225
  340. package/node_modules/hono/dist/helper/css/index.js +132 -137
  341. package/node_modules/hono/dist/helper/dev/index.js +44 -49
  342. package/node_modules/hono/dist/helper/factory/index.js +27 -27
  343. package/node_modules/hono/dist/helper/html/index.js +30 -39
  344. package/node_modules/hono/dist/helper/proxy/index.js +116 -88
  345. package/node_modules/hono/dist/helper/route/index.js +121 -43
  346. package/node_modules/hono/dist/helper/ssg/index.js +3 -18
  347. package/node_modules/hono/dist/helper/ssg/middleware.js +53 -40
  348. package/node_modules/hono/dist/helper/ssg/plugins.js +55 -36
  349. package/node_modules/hono/dist/helper/ssg/ssg.js +198 -283
  350. package/node_modules/hono/dist/helper/ssg/utils.js +53 -75
  351. package/node_modules/hono/dist/helper/streaming/index.js +2 -8
  352. package/node_modules/hono/dist/helper/streaming/sse.js +50 -61
  353. package/node_modules/hono/dist/helper/streaming/stream.js +22 -31
  354. package/node_modules/hono/dist/helper/streaming/text.js +9 -10
  355. package/node_modules/hono/dist/helper/streaming/utils.js +9 -12
  356. package/node_modules/hono/dist/helper/testing/index.js +16 -10
  357. package/node_modules/hono/dist/helper/websocket/index.js +49 -53
  358. package/node_modules/hono/dist/hono-base.js +342 -379
  359. package/node_modules/hono/dist/hono.js +27 -20
  360. package/node_modules/hono/dist/http-exception.js +53 -33
  361. package/node_modules/hono/dist/index.js +19 -6
  362. package/node_modules/hono/dist/jsx/base.js +231 -340
  363. package/node_modules/hono/dist/jsx/children.js +16 -20
  364. package/node_modules/hono/dist/jsx/components.js +118 -170
  365. package/node_modules/hono/dist/jsx/constants.js +9 -15
  366. package/node_modules/hono/dist/jsx/context.js +153 -150
  367. package/node_modules/hono/dist/jsx/dom/client.js +45 -48
  368. package/node_modules/hono/dist/jsx/dom/components.js +21 -29
  369. package/node_modules/hono/dist/jsx/dom/context.js +37 -44
  370. package/node_modules/hono/dist/jsx/dom/css.js +142 -147
  371. package/node_modules/hono/dist/jsx/dom/hooks/index.js +52 -40
  372. package/node_modules/hono/dist/jsx/dom/index.js +71 -134
  373. package/node_modules/hono/dist/jsx/dom/intrinsic-element/components.js +275 -359
  374. package/node_modules/hono/dist/jsx/dom/jsx-dev-runtime.js +14 -18
  375. package/node_modules/hono/dist/jsx/dom/jsx-runtime.js +2 -8
  376. package/node_modules/hono/dist/jsx/dom/render.js +492 -631
  377. package/node_modules/hono/dist/jsx/dom/server.js +32 -32
  378. package/node_modules/hono/dist/jsx/dom/utils.js +6 -8
  379. package/node_modules/hono/dist/jsx/hooks/index.js +236 -308
  380. package/node_modules/hono/dist/jsx/index.js +45 -98
  381. package/node_modules/hono/dist/jsx/intrinsic-element/common.js +20 -22
  382. package/node_modules/hono/dist/jsx/intrinsic-element/components.js +113 -154
  383. package/node_modules/hono/dist/jsx/intrinsic-elements.js +1 -0
  384. package/node_modules/hono/dist/jsx/jsx-dev-runtime.js +12 -16
  385. package/node_modules/hono/dist/jsx/jsx-runtime.js +29 -42
  386. package/node_modules/hono/dist/jsx/streaming.js +120 -142
  387. package/node_modules/hono/dist/jsx/types.js +1 -0
  388. package/node_modules/hono/dist/jsx/utils.js +105 -168
  389. package/node_modules/hono/dist/middleware/basic-auth/index.js +96 -63
  390. package/node_modules/hono/dist/middleware/bearer-auth/index.js +93 -89
  391. package/node_modules/hono/dist/middleware/body-limit/index.js +66 -51
  392. package/node_modules/hono/dist/middleware/cache/index.js +165 -190
  393. package/node_modules/hono/dist/middleware/combine/index.js +134 -73
  394. package/node_modules/hono/dist/middleware/compress/index.js +75 -69
  395. package/node_modules/hono/dist/middleware/context-storage/index.js +49 -19
  396. package/node_modules/hono/dist/middleware/cors/index.js +107 -86
  397. package/node_modules/hono/dist/middleware/csrf/index.js +103 -53
  398. package/node_modules/hono/dist/middleware/etag/digest.js +59 -77
  399. package/node_modules/hono/dist/middleware/etag/index.js +71 -70
  400. package/node_modules/hono/dist/middleware/ip-restriction/index.js +163 -158
  401. package/node_modules/hono/dist/middleware/jsx-renderer/index.js +97 -54
  402. package/node_modules/hono/dist/middleware/jwk/index.js +1 -4
  403. package/node_modules/hono/dist/middleware/jwk/jwk.js +116 -112
  404. package/node_modules/hono/dist/middleware/jwt/index.js +2 -10
  405. package/node_modules/hono/dist/middleware/jwt/jwt.js +114 -114
  406. package/node_modules/hono/dist/middleware/language/index.js +2 -15
  407. package/node_modules/hono/dist/middleware/language/language.js +180 -157
  408. package/node_modules/hono/dist/middleware/logger/index.js +43 -37
  409. package/node_modules/hono/dist/middleware/method-not-allowed/index.js +81 -66
  410. package/node_modules/hono/dist/middleware/method-override/index.js +101 -81
  411. package/node_modules/hono/dist/middleware/powered-by/index.js +23 -9
  412. package/node_modules/hono/dist/middleware/pretty-json/index.js +39 -16
  413. package/node_modules/hono/dist/middleware/request-id/index.js +1 -4
  414. package/node_modules/hono/dist/middleware/request-id/request-id.js +33 -20
  415. package/node_modules/hono/dist/middleware/secure-headers/index.js +1 -5
  416. package/node_modules/hono/dist/middleware/secure-headers/permissions-policy.js +1 -0
  417. package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +144 -155
  418. package/node_modules/hono/dist/middleware/serve-static/index.js +56 -72
  419. package/node_modules/hono/dist/middleware/serve-static/path.js +15 -17
  420. package/node_modules/hono/dist/middleware/timeout/index.js +40 -23
  421. package/node_modules/hono/dist/middleware/timing/index.js +2 -9
  422. package/node_modules/hono/dist/middleware/timing/timing.js +177 -97
  423. package/node_modules/hono/dist/middleware/trailing-slash/index.js +85 -37
  424. package/node_modules/hono/dist/preset/quick.js +17 -15
  425. package/node_modules/hono/dist/preset/tiny.js +14 -11
  426. package/node_modules/hono/dist/request/constants.js +4 -5
  427. package/node_modules/hono/dist/request.js +328 -319
  428. package/node_modules/hono/dist/router/linear-router/index.js +1 -4
  429. package/node_modules/hono/dist/router/linear-router/router.js +93 -120
  430. package/node_modules/hono/dist/router/pattern-router/index.js +1 -4
  431. package/node_modules/hono/dist/router/pattern-router/router.js +39 -40
  432. package/node_modules/hono/dist/router/reg-exp-router/index.js +1 -7
  433. package/node_modules/hono/dist/router/reg-exp-router/matcher.js +17 -23
  434. package/node_modules/hono/dist/router/reg-exp-router/node.js +87 -110
  435. package/node_modules/hono/dist/router/reg-exp-router/prepared-router.js +89 -137
  436. package/node_modules/hono/dist/router/reg-exp-router/router.js +92 -129
  437. package/node_modules/hono/dist/router/reg-exp-router/trie.js +69 -64
  438. package/node_modules/hono/dist/router/smart-router/index.js +1 -4
  439. package/node_modules/hono/dist/router/smart-router/router.js +46 -55
  440. package/node_modules/hono/dist/router/trie-router/index.js +1 -4
  441. package/node_modules/hono/dist/router/trie-router/node.js +131 -162
  442. package/node_modules/hono/dist/router/trie-router/router.js +11 -14
  443. package/node_modules/hono/dist/router/utils.js +4 -5
  444. package/node_modules/hono/dist/router.js +35 -14
  445. package/node_modules/hono/dist/types/adapter/aws-lambda/conninfo.d.ts +4 -1
  446. package/node_modules/hono/dist/types/adapter/aws-lambda/handler.d.ts +150 -104
  447. package/node_modules/hono/dist/types/adapter/aws-lambda/index.d.ts +4 -8
  448. package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +152 -122
  449. package/node_modules/hono/dist/types/adapter/bun/conninfo.d.ts +4 -1
  450. package/node_modules/hono/dist/types/adapter/bun/index.d.ts +6 -10
  451. package/node_modules/hono/dist/types/adapter/bun/serve-static.d.ts +7 -2
  452. package/node_modules/hono/dist/types/adapter/bun/server.d.ts +4 -5
  453. package/node_modules/hono/dist/types/adapter/bun/ssg.d.ts +5 -1
  454. package/node_modules/hono/dist/types/adapter/bun/websocket.d.ts +31 -16
  455. package/node_modules/hono/dist/types/adapter/cloudflare-pages/conninfo.d.ts +4 -1
  456. package/node_modules/hono/dist/types/adapter/cloudflare-pages/handler.d.ts +29 -17
  457. package/node_modules/hono/dist/types/adapter/cloudflare-pages/index.d.ts +3 -7
  458. package/node_modules/hono/dist/types/adapter/cloudflare-workers/conninfo.d.ts +6 -1
  459. package/node_modules/hono/dist/types/adapter/cloudflare-workers/index.d.ts +4 -7
  460. package/node_modules/hono/dist/types/adapter/cloudflare-workers/serve-static-module.d.ts +5 -2
  461. package/node_modules/hono/dist/types/adapter/cloudflare-workers/serve-static.d.ts +10 -5
  462. package/node_modules/hono/dist/types/adapter/cloudflare-workers/utils.d.ts +10 -2
  463. package/node_modules/hono/dist/types/adapter/cloudflare-workers/websocket.d.ts +6 -1
  464. package/node_modules/hono/dist/types/adapter/deno/conninfo.d.ts +4 -1
  465. package/node_modules/hono/dist/types/adapter/deno/deno.d.ts +1 -0
  466. package/node_modules/hono/dist/types/adapter/deno/index.d.ts +5 -8
  467. package/node_modules/hono/dist/types/adapter/deno/serve-static.d.ts +7 -2
  468. package/node_modules/hono/dist/types/adapter/deno/ssg.d.ts +5 -1
  469. package/node_modules/hono/dist/types/adapter/deno/websocket.d.ts +6 -1
  470. package/node_modules/hono/dist/types/adapter/lambda-edge/conninfo.d.ts +6 -1
  471. package/node_modules/hono/dist/types/adapter/lambda-edge/handler.d.ts +83 -57
  472. package/node_modules/hono/dist/types/adapter/lambda-edge/index.d.ts +3 -7
  473. package/node_modules/hono/dist/types/adapter/netlify/conninfo.d.ts +4 -1
  474. package/node_modules/hono/dist/types/adapter/netlify/handler.d.ts +6 -1
  475. package/node_modules/hono/dist/types/adapter/netlify/index.d.ts +3 -5
  476. package/node_modules/hono/dist/types/adapter/netlify/mod.d.ts +3 -2
  477. package/node_modules/hono/dist/types/adapter/service-worker/handler.d.ts +9 -7
  478. package/node_modules/hono/dist/types/adapter/service-worker/index.d.ts +7 -9
  479. package/node_modules/hono/dist/types/adapter/service-worker/types.d.ts +12 -7
  480. package/node_modules/hono/dist/types/adapter/vercel/conninfo.d.ts +6 -1
  481. package/node_modules/hono/dist/types/adapter/vercel/handler.d.ts +6 -1
  482. package/node_modules/hono/dist/types/adapter/vercel/index.d.ts +3 -6
  483. package/node_modules/hono/dist/types/client/client.d.ts +5 -3
  484. package/node_modules/hono/dist/types/client/fetch-result-please.d.ts +21 -19
  485. package/node_modules/hono/dist/types/client/index.d.ts +5 -7
  486. package/node_modules/hono/dist/types/client/types.d.ts +134 -159
  487. package/node_modules/hono/dist/types/client/utils.d.ts +6 -4
  488. package/node_modules/hono/dist/types/compose.d.ts +4 -2
  489. package/node_modules/hono/dist/types/context.d.ts +335 -335
  490. package/node_modules/hono/dist/types/helper/accepts/accepts.d.ts +11 -9
  491. package/node_modules/hono/dist/types/helper/accepts/index.d.ts +2 -5
  492. package/node_modules/hono/dist/types/helper/adapter/index.d.ts +4 -6
  493. package/node_modules/hono/dist/types/helper/conninfo/index.d.ts +2 -5
  494. package/node_modules/hono/dist/types/helper/conninfo/types.d.ts +25 -23
  495. package/node_modules/hono/dist/types/helper/cookie/index.d.ts +10 -12
  496. package/node_modules/hono/dist/types/helper/css/common.d.ts +11 -9
  497. package/node_modules/hono/dist/types/helper/css/index.d.ts +26 -28
  498. package/node_modules/hono/dist/types/helper/dev/index.d.ts +10 -12
  499. package/node_modules/hono/dist/types/helper/factory/index.d.ts +26 -73
  500. package/node_modules/hono/dist/types/helper/html/index.d.ts +4 -7
  501. package/node_modules/hono/dist/types/helper/proxy/index.d.ts +19 -21
  502. package/node_modules/hono/dist/types/helper/route/index.d.ts +4 -2
  503. package/node_modules/hono/dist/types/helper/ssg/index.d.ts +4 -7
  504. package/node_modules/hono/dist/types/helper/ssg/middleware.d.ts +8 -6
  505. package/node_modules/hono/dist/types/helper/ssg/plugins.d.ts +3 -1
  506. package/node_modules/hono/dist/types/helper/ssg/ssg.d.ts +38 -36
  507. package/node_modules/hono/dist/types/helper/ssg/utils.d.ts +5 -3
  508. package/node_modules/hono/dist/types/helper/streaming/index.d.ts +4 -8
  509. package/node_modules/hono/dist/types/helper/streaming/sse.d.ts +10 -8
  510. package/node_modules/hono/dist/types/helper/streaming/stream.d.ts +4 -2
  511. package/node_modules/hono/dist/types/helper/streaming/text.d.ts +4 -2
  512. package/node_modules/hono/dist/types/helper/streaming/utils.d.ts +2 -0
  513. package/node_modules/hono/dist/types/helper/testing/index.d.ts +7 -9
  514. package/node_modules/hono/dist/types/helper/websocket/index.d.ts +30 -33
  515. package/node_modules/hono/dist/types/hono-base.d.ts +208 -210
  516. package/node_modules/hono/dist/types/hono.d.ts +11 -10
  517. package/node_modules/hono/dist/types/http-exception.d.ts +20 -22
  518. package/node_modules/hono/dist/types/index.d.ts +6 -37
  519. package/node_modules/hono/dist/types/jsx/base.d.ts +36 -34
  520. package/node_modules/hono/dist/types/jsx/children.d.ts +8 -6
  521. package/node_modules/hono/dist/types/jsx/components.d.ts +8 -5
  522. package/node_modules/hono/dist/types/jsx/constants.d.ts +2 -0
  523. package/node_modules/hono/dist/types/jsx/context.d.ts +9 -6
  524. package/node_modules/hono/dist/types/jsx/dom/client.d.ts +9 -10
  525. package/node_modules/hono/dist/types/jsx/dom/components.d.ts +9 -6
  526. package/node_modules/hono/dist/types/jsx/dom/context.d.ts +3 -1
  527. package/node_modules/hono/dist/types/jsx/dom/css.d.ts +27 -30
  528. package/node_modules/hono/dist/types/jsx/dom/hooks/index.d.ts +11 -12
  529. package/node_modules/hono/dist/types/jsx/dom/index.d.ts +79 -83
  530. package/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +9 -5
  531. package/node_modules/hono/dist/types/jsx/dom/jsx-dev-runtime.d.ts +4 -6
  532. package/node_modules/hono/dist/types/jsx/dom/jsx-runtime.d.ts +3 -7
  533. package/node_modules/hono/dist/types/jsx/dom/render.d.ts +32 -50
  534. package/node_modules/hono/dist/types/jsx/dom/server.d.ts +87 -85
  535. package/node_modules/hono/dist/types/jsx/dom/utils.d.ts +2 -0
  536. package/node_modules/hono/dist/types/jsx/hooks/index.d.ts +16 -16
  537. package/node_modules/hono/dist/types/jsx/index.d.ts +71 -73
  538. package/node_modules/hono/dist/types/jsx/intrinsic-element/common.d.ts +3 -1
  539. package/node_modules/hono/dist/types/jsx/intrinsic-element/components.d.ts +7 -4
  540. package/node_modules/hono/dist/types/jsx/intrinsic-elements.d.ts +708 -708
  541. package/node_modules/hono/dist/types/jsx/jsx-dev-runtime.d.ts +4 -7
  542. package/node_modules/hono/dist/types/jsx/jsx-runtime.d.ts +7 -10
  543. package/node_modules/hono/dist/types/jsx/streaming.d.ts +9 -10
  544. package/node_modules/hono/dist/types/jsx/types.d.ts +12 -13
  545. package/node_modules/hono/dist/types/jsx/utils.d.ts +2 -0
  546. package/node_modules/hono/dist/types/middleware/basic-auth/index.d.ts +17 -19
  547. package/node_modules/hono/dist/types/middleware/bearer-auth/index.d.ts +46 -48
  548. package/node_modules/hono/dist/types/middleware/body-limit/index.d.ts +6 -8
  549. package/node_modules/hono/dist/types/middleware/cache/index.d.ts +13 -15
  550. package/node_modules/hono/dist/types/middleware/combine/index.d.ts +4 -6
  551. package/node_modules/hono/dist/types/middleware/compress/index.d.ts +9 -10
  552. package/node_modules/hono/dist/types/middleware/context-storage/index.d.ts +4 -6
  553. package/node_modules/hono/dist/types/middleware/cors/index.d.ts +10 -12
  554. package/node_modules/hono/dist/types/middleware/csrf/index.d.ts +6 -8
  555. package/node_modules/hono/dist/types/middleware/etag/digest.d.ts +2 -0
  556. package/node_modules/hono/dist/types/middleware/etag/index.d.ts +6 -8
  557. package/node_modules/hono/dist/types/middleware/ip-restriction/index.d.ts +11 -12
  558. package/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +11 -11
  559. package/node_modules/hono/dist/types/middleware/jwk/index.d.ts +2 -1
  560. package/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +20 -23
  561. package/node_modules/hono/dist/types/middleware/jwt/index.d.ts +7 -6
  562. package/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +28 -30
  563. package/node_modules/hono/dist/types/middleware/language/index.d.ts +6 -5
  564. package/node_modules/hono/dist/types/middleware/language/language.d.ts +42 -44
  565. package/node_modules/hono/dist/types/middleware/logger/index.d.ts +3 -5
  566. package/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +7 -9
  567. package/node_modules/hono/dist/types/middleware/method-override/index.d.ts +14 -16
  568. package/node_modules/hono/dist/types/middleware/powered-by/index.d.ts +8 -10
  569. package/node_modules/hono/dist/types/middleware/pretty-json/index.d.ts +18 -20
  570. package/node_modules/hono/dist/types/middleware/request-id/index.d.ts +6 -5
  571. package/node_modules/hono/dist/types/middleware/request-id/request-id.d.ts +9 -11
  572. package/node_modules/hono/dist/types/middleware/secure-headers/index.d.ts +6 -6
  573. package/node_modules/hono/dist/types/middleware/secure-headers/permissions-policy.d.ts +2 -0
  574. package/node_modules/hono/dist/types/middleware/secure-headers/secure-headers.d.ts +55 -57
  575. package/node_modules/hono/dist/types/middleware/serve-static/index.d.ts +24 -24
  576. package/node_modules/hono/dist/types/middleware/serve-static/path.d.ts +2 -0
  577. package/node_modules/hono/dist/types/middleware/timeout/index.d.ts +5 -7
  578. package/node_modules/hono/dist/types/middleware/timing/index.d.ts +6 -5
  579. package/node_modules/hono/dist/types/middleware/timing/timing.d.ts +17 -20
  580. package/node_modules/hono/dist/types/middleware/trailing-slash/index.d.ts +35 -37
  581. package/node_modules/hono/dist/types/preset/quick.d.ts +6 -9
  582. package/node_modules/hono/dist/types/preset/tiny.d.ts +6 -9
  583. package/node_modules/hono/dist/types/request/constants.d.ts +2 -0
  584. package/node_modules/hono/dist/types/request.d.ts +288 -286
  585. package/node_modules/hono/dist/types/router/linear-router/index.d.ts +2 -5
  586. package/node_modules/hono/dist/types/router/linear-router/router.d.ts +7 -5
  587. package/node_modules/hono/dist/types/router/pattern-router/index.d.ts +2 -5
  588. package/node_modules/hono/dist/types/router/pattern-router/router.d.ts +7 -5
  589. package/node_modules/hono/dist/types/router/reg-exp-router/index.d.ts +3 -6
  590. package/node_modules/hono/dist/types/router/reg-exp-router/matcher.d.ts +3 -1
  591. package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +6 -4
  592. package/node_modules/hono/dist/types/router/reg-exp-router/prepared-router.d.ts +11 -10
  593. package/node_modules/hono/dist/types/router/reg-exp-router/router.d.ts +10 -9
  594. package/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +7 -5
  595. package/node_modules/hono/dist/types/router/smart-router/index.d.ts +2 -5
  596. package/node_modules/hono/dist/types/router/smart-router/router.d.ts +11 -9
  597. package/node_modules/hono/dist/types/router/trie-router/index.d.ts +2 -5
  598. package/node_modules/hono/dist/types/router/trie-router/node.d.ts +6 -4
  599. package/node_modules/hono/dist/types/router/trie-router/router.d.ts +7 -5
  600. package/node_modules/hono/dist/types/router/utils.d.ts +2 -0
  601. package/node_modules/hono/dist/types/router.d.ts +23 -22
  602. package/node_modules/hono/dist/types/types.d.ts +146 -505
  603. package/node_modules/hono/dist/types/utils/accept.d.ts +5 -3
  604. package/node_modules/hono/dist/types/utils/basic-auth.d.ts +4 -2
  605. package/node_modules/hono/dist/types/utils/body.d.ts +46 -50
  606. package/node_modules/hono/dist/types/utils/buffer.d.ts +7 -5
  607. package/node_modules/hono/dist/types/utils/color.d.ts +2 -0
  608. package/node_modules/hono/dist/types/utils/compress.d.ts +2 -0
  609. package/node_modules/hono/dist/types/utils/concurrent.d.ts +6 -4
  610. package/node_modules/hono/dist/types/utils/constants.d.ts +2 -0
  611. package/node_modules/hono/dist/types/utils/cookie.d.ts +20 -18
  612. package/node_modules/hono/dist/types/utils/crypto.d.ts +5 -7
  613. package/node_modules/hono/dist/types/utils/encode.d.ts +2 -0
  614. package/node_modules/hono/dist/types/utils/filepath.d.ts +5 -3
  615. package/node_modules/hono/dist/types/utils/handler.d.ts +2 -0
  616. package/node_modules/hono/dist/types/utils/headers.d.ts +2 -0
  617. package/node_modules/hono/dist/types/utils/html.d.ts +11 -9
  618. package/node_modules/hono/dist/types/utils/http-status.d.ts +2 -0
  619. package/node_modules/hono/dist/types/utils/ipaddr.d.ts +4 -6
  620. package/node_modules/hono/dist/types/utils/jwt/index.d.ts +18 -12
  621. package/node_modules/hono/dist/types/utils/jwt/jwa.d.ts +15 -13
  622. package/node_modules/hono/dist/types/utils/jwt/jws.d.ts +4 -7
  623. package/node_modules/hono/dist/types/utils/jwt/jwt.d.ts +26 -29
  624. package/node_modules/hono/dist/types/utils/jwt/types.d.ts +48 -45
  625. package/node_modules/hono/dist/types/utils/jwt/utf8.d.ts +2 -0
  626. package/node_modules/hono/dist/types/utils/mime.d.ts +60 -57
  627. package/node_modules/hono/dist/types/utils/stream.d.ts +27 -25
  628. package/node_modules/hono/dist/types/utils/types.d.ts +14 -26
  629. package/node_modules/hono/dist/types/utils/url.d.ts +2 -0
  630. package/node_modules/hono/dist/types/validator/index.d.ts +3 -7
  631. package/node_modules/hono/dist/types/validator/utils.d.ts +6 -8
  632. package/node_modules/hono/dist/types/validator/validator.d.ts +11 -9
  633. package/node_modules/hono/dist/types.js +4 -6
  634. package/node_modules/hono/dist/utils/accept.js +185 -212
  635. package/node_modules/hono/dist/utils/basic-auth.js +18 -21
  636. package/node_modules/hono/dist/utils/body.js +87 -92
  637. package/node_modules/hono/dist/utils/buffer.js +44 -71
  638. package/node_modules/hono/dist/utils/color.js +33 -21
  639. package/node_modules/hono/dist/utils/compress.js +11 -5
  640. package/node_modules/hono/dist/utils/concurrent.js +29 -38
  641. package/node_modules/hono/dist/utils/constants.js +7 -5
  642. package/node_modules/hono/dist/utils/cookie.js +114 -163
  643. package/node_modules/hono/dist/utils/crypto.js +30 -40
  644. package/node_modules/hono/dist/utils/encode.js +30 -26
  645. package/node_modules/hono/dist/utils/filepath.js +23 -33
  646. package/node_modules/hono/dist/utils/handler.js +10 -11
  647. package/node_modules/hono/dist/utils/headers.js +1 -0
  648. package/node_modules/hono/dist/utils/html.js +97 -117
  649. package/node_modules/hono/dist/utils/http-status.js +1 -0
  650. package/node_modules/hono/dist/utils/ipaddr.js +227 -279
  651. package/node_modules/hono/dist/utils/jwt/index.js +12 -4
  652. package/node_modules/hono/dist/utils/jwt/jwa.js +24 -20
  653. package/node_modules/hono/dist/utils/jwt/jws.js +115 -174
  654. package/node_modules/hono/dist/utils/jwt/jwt.js +120 -197
  655. package/node_modules/hono/dist/utils/jwt/types.js +79 -95
  656. package/node_modules/hono/dist/utils/jwt/utf8.js +9 -7
  657. package/node_modules/hono/dist/utils/mime.js +74 -79
  658. package/node_modules/hono/dist/utils/stream.js +86 -88
  659. package/node_modules/hono/dist/utils/types.js +1 -0
  660. package/node_modules/hono/dist/utils/url.js +187 -215
  661. package/node_modules/hono/dist/validator/index.js +1 -4
  662. package/node_modules/hono/dist/validator/utils.js +1 -0
  663. package/node_modules/hono/dist/validator/validator.js +61 -83
  664. package/node_modules/hono/package.json +27 -27
  665. package/package.json +2 -2
  666. package/profiles/README.md +20 -0
  667. package/profiles/index.json +2 -1
  668. package/profiles/sales/0.1.profile.json +252 -0
  669. package/server.js +99 -0
  670. package/dist/ui/assets/index-DWpjjPIf.js +0 -110
@@ -134,6 +134,13 @@ var SPClient = class {
134
134
  sessionCookie = "";
135
135
  apiKey = "";
136
136
  receiptRetry;
137
+ /** Set when a call comes back 401 while we held a session — distinct from
138
+ * never having logged in. Cleared the moment a fresh cookie is configured. */
139
+ lockReason = null;
140
+ /** Single-flight per client instance: only the FIRST 401 after a session
141
+ * was active tells the control plane. Concurrent in-flight calls that were
142
+ * all sent under the same now-dead cookie would otherwise all report it. */
143
+ sessionExpiredNotified = false;
137
144
  /** The AS base URL this client talks to (for provenance records). */
138
145
  get url() {
139
146
  return this.baseUrl;
@@ -143,6 +150,29 @@ var SPClient = class {
143
150
  }
144
151
  setSessionCookie(cookie) {
145
152
  this.sessionCookie = cookie;
153
+ this.lockReason = null;
154
+ this.sessionExpiredNotified = false;
155
+ }
156
+ /**
157
+ * Drop the session because the control plane learned (by whatever path —
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.
167
+ */
168
+ clearSession(reason = "expired") {
169
+ this.sessionCookie = "";
170
+ this.lockReason = reason;
171
+ }
172
+ /** Why we are currently locked, if known. `null` means the default
173
+ * boot-locked case (nobody has signed in yet this run). */
174
+ getLockReason() {
175
+ return this.sessionCookie === "" ? this.lockReason : null;
146
176
  }
147
177
  /**
148
178
  * Has anyone signed in yet this run?
@@ -174,10 +204,20 @@ var SPClient = class {
174
204
  if (this.apiKey) {
175
205
  headers["X-API-Key"] = this.apiKey;
176
206
  }
177
- return globalThis.fetch(url, {
207
+ const hadSession = this.sessionCookie !== "";
208
+ const res = await globalThis.fetch(url, {
178
209
  ...init,
179
210
  headers
180
211
  });
212
+ if (res.status === 401 && hadSession) {
213
+ this.sessionCookie = "";
214
+ this.lockReason = "expired";
215
+ if (!this.sessionExpiredNotified) {
216
+ this.sessionExpiredNotified = true;
217
+ void notifyControlPlane("session-expired");
218
+ }
219
+ }
220
+ return res;
181
221
  }
182
222
  /**
183
223
  * Get SP public key.
@@ -331,13 +371,52 @@ var SPClient = class {
331
371
 
332
372
  // src/lib/attestation-cache.ts
333
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
+ };
334
406
  function isCommitmentDowngrade(auth) {
335
407
  const requiresReview = auth.signedCommitmentMode === "review" || auth.signedCommitmentMode === "review_above_cap";
336
408
  return requiresReview && (auth.deferredCommitmentDomains ?? []).length === 0;
337
409
  }
338
410
  var AttestationCache = class {
339
- constructor(spClient) {
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) {
340
418
  this.spClient = spClient;
419
+ this.dataDir = dataDir2;
341
420
  }
342
421
  spPublicKey = null;
343
422
  spPublicKeyFetchedAt = 0;
@@ -347,15 +426,29 @@ var AttestationCache = class {
347
426
  authorizations = /* @__PURE__ */ new Map();
348
427
  lastSync = 0;
349
428
  /**
350
- * 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.
351
437
  */
352
438
  async getPublicKey() {
353
439
  const now = Math.floor(Date.now() / 1e3);
354
- if (this.spPublicKey && now - this.spPublicKeyFetchedAt < this.SP_PUBKEY_TTL) {
355
- return this.spPublicKey;
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
+ }
356
451
  }
357
- this.spPublicKey = await this.spClient.getPublicKey();
358
- this.spPublicKeyFetchedAt = now;
359
452
  return this.spPublicKey;
360
453
  }
361
454
  /**
@@ -465,18 +558,18 @@ var AttestationCache = class {
465
558
  };
466
559
 
467
560
  // src/lib/gate-store.ts
468
- import { mkdirSync, readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, unlinkSync } from "fs";
561
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
469
562
  import { homedir } from "os";
470
- import { dirname, join as join2 } from "path";
563
+ import { dirname as dirname2, join as join3 } from "path";
471
564
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
472
- var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ?? join2(homedir(), ".suveren");
565
+ var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ?? join3(homedir(), ".suveren");
473
566
  var GateStore = class {
474
567
  entries = /* @__PURE__ */ new Map();
475
568
  baseDir;
476
569
  vaultKey = null;
477
570
  constructor(filePath) {
478
571
  if (filePath && filePath.endsWith(".json")) {
479
- this.baseDir = dirname(filePath);
572
+ this.baseDir = dirname2(filePath);
480
573
  } else {
481
574
  this.baseDir = filePath ?? DEFAULT_DIR;
482
575
  }
@@ -487,13 +580,13 @@ var GateStore = class {
487
580
  */
488
581
  setVaultKey(key) {
489
582
  this.vaultKey = key;
490
- if (existsSync2(this.encryptedFilePath)) {
583
+ if (existsSync3(this.encryptedFilePath)) {
491
584
  this.loadEncrypted();
492
585
  } else if (this.entries.size > 0) {
493
586
  this.persistEncrypted();
494
- if (existsSync2(this.plaintextFilePath)) {
587
+ if (existsSync3(this.plaintextFilePath)) {
495
588
  try {
496
- unlinkSync(this.plaintextFilePath);
589
+ unlinkSync2(this.plaintextFilePath);
497
590
  } catch {
498
591
  }
499
592
  }
@@ -513,6 +606,30 @@ var GateStore = class {
513
606
  this.entries.delete(path);
514
607
  this.persist();
515
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
+ }
516
633
  // ─── Encryption helpers ─────────────────────────────────────────────────
517
634
  encrypt(plaintext) {
518
635
  if (!this.vaultKey) throw new Error("No vault key");
@@ -542,19 +659,19 @@ var GateStore = class {
542
659
  }
543
660
  // ─── File paths ─────────────────────────────────────────────────────────
544
661
  get plaintextFilePath() {
545
- return join2(this.baseDir, "gates.json");
662
+ return join3(this.baseDir, "gates.json");
546
663
  }
547
664
  get encryptedFilePath() {
548
- return join2(this.baseDir, "gates.enc.json");
665
+ return join3(this.baseDir, "gates.enc.json");
549
666
  }
550
667
  // ─── Load / Persist ─────────────────────────────────────────────────────
551
668
  loadPlaintext() {
552
- if (!existsSync2(this.plaintextFilePath)) {
553
- mkdirSync(this.baseDir, { recursive: true });
669
+ if (!existsSync3(this.plaintextFilePath)) {
670
+ mkdirSync2(this.baseDir, { recursive: true });
554
671
  return;
555
672
  }
556
673
  try {
557
- const raw = readFileSync2(this.plaintextFilePath, "utf-8");
674
+ const raw = readFileSync3(this.plaintextFilePath, "utf-8");
558
675
  const data = JSON.parse(raw);
559
676
  this.entries = new Map(Object.entries(data.entries));
560
677
  } catch {
@@ -563,9 +680,9 @@ var GateStore = class {
563
680
  }
564
681
  }
565
682
  loadEncrypted() {
566
- if (!existsSync2(this.encryptedFilePath)) return;
683
+ if (!existsSync3(this.encryptedFilePath)) return;
567
684
  try {
568
- const raw = readFileSync2(this.encryptedFilePath, "utf-8");
685
+ const raw = readFileSync3(this.encryptedFilePath, "utf-8");
569
686
  const data = JSON.parse(raw);
570
687
  this.entries = /* @__PURE__ */ new Map();
571
688
  for (const [key, blob] of Object.entries(data.entries)) {
@@ -589,8 +706,8 @@ var GateStore = class {
589
706
  version: 1,
590
707
  entries: Object.fromEntries(this.entries)
591
708
  };
592
- mkdirSync(this.baseDir, { recursive: true, mode: 448 });
593
- writeFileSync(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
709
+ mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
710
+ writeFileSync2(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
594
711
  }
595
712
  persistEncrypted() {
596
713
  const data = {
@@ -600,17 +717,17 @@ var GateStore = class {
600
717
  for (const [key, entry] of this.entries) {
601
718
  data.entries[key] = this.encrypt(JSON.stringify(entry));
602
719
  }
603
- mkdirSync(this.baseDir, { recursive: true, mode: 448 });
604
- writeFileSync(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
720
+ mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
721
+ writeFileSync2(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
605
722
  }
606
723
  };
607
724
 
608
725
  // src/lib/execution-log.ts
609
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
726
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
610
727
  import { homedir as homedir2 } from "os";
611
- import { dirname as dirname2, join as join3 } from "path";
728
+ import { dirname as dirname3, join as join4 } from "path";
612
729
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
613
- var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ?? join3(homedir2(), ".suveren");
730
+ var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ?? join4(homedir2(), ".suveren");
614
731
  var MAX_AGE_SECONDS = 31 * 24 * 60 * 60;
615
732
  var ExecutionLog = class {
616
733
  entries = [];
@@ -618,7 +735,7 @@ var ExecutionLog = class {
618
735
  vaultKey = null;
619
736
  constructor(filePath) {
620
737
  if (filePath && filePath.endsWith(".json")) {
621
- this.baseDir = dirname2(filePath);
738
+ this.baseDir = dirname3(filePath);
622
739
  } else {
623
740
  this.baseDir = filePath ?? DEFAULT_DIR2;
624
741
  }
@@ -629,13 +746,13 @@ var ExecutionLog = class {
629
746
  */
630
747
  setVaultKey(key) {
631
748
  this.vaultKey = key;
632
- if (existsSync3(this.encryptedFilePath)) {
749
+ if (existsSync4(this.encryptedFilePath)) {
633
750
  this.loadEncrypted();
634
751
  } else if (this.entries.length > 0) {
635
752
  this.persistEncrypted();
636
- if (existsSync3(this.plaintextFilePath)) {
753
+ if (existsSync4(this.plaintextFilePath)) {
637
754
  try {
638
- unlinkSync2(this.plaintextFilePath);
755
+ unlinkSync3(this.plaintextFilePath);
639
756
  } catch {
640
757
  }
641
758
  }
@@ -657,14 +774,23 @@ var ExecutionLog = class {
657
774
  * @param field - The execution field to sum ("_count" for plain counting)
658
775
  * @param window - Time window (daily, weekly, monthly)
659
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.
660
782
  */
661
- sumByWindow(profileId, path, field, window, now = Math.floor(Date.now() / 1e3)) {
783
+ sumByWindow(profileId, path, field, window, now = Math.floor(Date.now() / 1e3), actionTypes) {
662
784
  const cutoff = windowCutoff(window, now);
663
785
  let total = 0;
664
786
  for (const entry of this.entries) {
665
787
  if (entry.profileId !== profileId) continue;
666
788
  if (entry.path !== path) continue;
667
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
+ }
668
794
  if (field === "_count") {
669
795
  total += 1;
670
796
  } else {
@@ -728,19 +854,19 @@ var ExecutionLog = class {
728
854
  }
729
855
  // ─── File paths ─────────────────────────────────────────────────────────
730
856
  get plaintextFilePath() {
731
- return join3(this.baseDir, "execution-log.json");
857
+ return join4(this.baseDir, "execution-log.json");
732
858
  }
733
859
  get encryptedFilePath() {
734
- return join3(this.baseDir, "execution-log.enc.json");
860
+ return join4(this.baseDir, "execution-log.enc.json");
735
861
  }
736
862
  // ─── Load / Persist ─────────────────────────────────────────────────────
737
863
  loadPlaintext() {
738
- if (!existsSync3(this.plaintextFilePath)) {
739
- mkdirSync2(this.baseDir, { recursive: true });
864
+ if (!existsSync4(this.plaintextFilePath)) {
865
+ mkdirSync3(this.baseDir, { recursive: true });
740
866
  return;
741
867
  }
742
868
  try {
743
- const raw = readFileSync3(this.plaintextFilePath, "utf-8");
869
+ const raw = readFileSync4(this.plaintextFilePath, "utf-8");
744
870
  const data = JSON.parse(raw);
745
871
  this.entries = data.entries;
746
872
  this.prune();
@@ -750,9 +876,9 @@ var ExecutionLog = class {
750
876
  }
751
877
  }
752
878
  loadEncrypted() {
753
- if (!existsSync3(this.encryptedFilePath)) return;
879
+ if (!existsSync4(this.encryptedFilePath)) return;
754
880
  try {
755
- const raw = readFileSync3(this.encryptedFilePath, "utf-8");
881
+ const raw = readFileSync4(this.encryptedFilePath, "utf-8");
756
882
  const data = JSON.parse(raw);
757
883
  const decrypted = this.decrypt(data.blob);
758
884
  const logFile = JSON.parse(decrypted);
@@ -772,8 +898,8 @@ var ExecutionLog = class {
772
898
  }
773
899
  persistPlaintext() {
774
900
  const data = { version: 1, entries: this.entries };
775
- mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
776
- writeFileSync2(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
901
+ mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
902
+ writeFileSync3(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
777
903
  }
778
904
  persistEncrypted() {
779
905
  const logFile = { version: 1, entries: this.entries };
@@ -781,8 +907,8 @@ var ExecutionLog = class {
781
907
  version: 1,
782
908
  blob: this.encrypt(JSON.stringify(logFile))
783
909
  };
784
- mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
785
- writeFileSync2(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
910
+ mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
911
+ writeFileSync3(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
786
912
  }
787
913
  };
788
914
  function windowCutoff(window, now) {
@@ -799,11 +925,11 @@ function windowCutoff(window, now) {
799
925
  }
800
926
 
801
927
  // src/lib/denial-log.ts
802
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
928
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, unlinkSync as unlinkSync4 } from "fs";
803
929
  import { homedir as homedir3 } from "os";
804
- import { dirname as dirname3, join as join4 } from "path";
930
+ import { dirname as dirname4, join as join5 } from "path";
805
931
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes3 } from "crypto";
806
- var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ?? join4(homedir3(), ".suveren");
932
+ var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ?? join5(homedir3(), ".suveren");
807
933
  var MAX_RECORDS = 200;
808
934
  var MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
809
935
  var DenialLog = class {
@@ -811,18 +937,18 @@ var DenialLog = class {
811
937
  baseDir;
812
938
  vaultKey = null;
813
939
  constructor(filePath) {
814
- this.baseDir = filePath && filePath.endsWith(".json") ? dirname3(filePath) : filePath ?? DEFAULT_DIR3;
940
+ this.baseDir = filePath && filePath.endsWith(".json") ? dirname4(filePath) : filePath ?? DEFAULT_DIR3;
815
941
  this.loadPlaintext();
816
942
  }
817
943
  setVaultKey(key) {
818
944
  this.vaultKey = key;
819
- if (existsSync4(this.encryptedFilePath)) {
945
+ if (existsSync5(this.encryptedFilePath)) {
820
946
  this.loadEncrypted();
821
947
  } else if (this.records.length > 0) {
822
948
  this.persistEncrypted();
823
- if (existsSync4(this.plaintextFilePath)) {
949
+ if (existsSync5(this.plaintextFilePath)) {
824
950
  try {
825
- unlinkSync3(this.plaintextFilePath);
951
+ unlinkSync4(this.plaintextFilePath);
826
952
  } catch {
827
953
  }
828
954
  }
@@ -870,18 +996,18 @@ var DenialLog = class {
870
996
  return Buffer.concat([decipher.update(Buffer.from(blob.ciphertext, "hex")), decipher.final()]).toString("utf8");
871
997
  }
872
998
  get plaintextFilePath() {
873
- return join4(this.baseDir, "denials.json");
999
+ return join5(this.baseDir, "denials.json");
874
1000
  }
875
1001
  get encryptedFilePath() {
876
- return join4(this.baseDir, "denials.enc.json");
1002
+ return join5(this.baseDir, "denials.enc.json");
877
1003
  }
878
1004
  loadPlaintext() {
879
- if (!existsSync4(this.plaintextFilePath)) {
880
- mkdirSync3(this.baseDir, { recursive: true });
1005
+ if (!existsSync5(this.plaintextFilePath)) {
1006
+ mkdirSync4(this.baseDir, { recursive: true });
881
1007
  return;
882
1008
  }
883
1009
  try {
884
- const data = JSON.parse(readFileSync4(this.plaintextFilePath, "utf-8"));
1010
+ const data = JSON.parse(readFileSync5(this.plaintextFilePath, "utf-8"));
885
1011
  this.records = data.records ?? [];
886
1012
  } catch {
887
1013
  console.error(`[DenialLog] Could not parse ${this.plaintextFilePath}, starting fresh`);
@@ -889,9 +1015,9 @@ var DenialLog = class {
889
1015
  }
890
1016
  }
891
1017
  loadEncrypted() {
892
- if (!existsSync4(this.encryptedFilePath)) return;
1018
+ if (!existsSync5(this.encryptedFilePath)) return;
893
1019
  try {
894
- const data = JSON.parse(readFileSync4(this.encryptedFilePath, "utf-8"));
1020
+ const data = JSON.parse(readFileSync5(this.encryptedFilePath, "utf-8"));
895
1021
  const logFile = JSON.parse(this.decrypt(data.blob));
896
1022
  this.records = logFile.records ?? [];
897
1023
  } catch (err) {
@@ -905,23 +1031,23 @@ var DenialLog = class {
905
1031
  }
906
1032
  persistPlaintext() {
907
1033
  const data = { version: 1, records: this.records };
908
- mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
909
- writeFileSync3(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1034
+ mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1035
+ writeFileSync4(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
910
1036
  }
911
1037
  persistEncrypted() {
912
1038
  const logFile = { version: 1, records: this.records };
913
1039
  const data = { version: 1, blob: this.encrypt(JSON.stringify(logFile)) };
914
- mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
915
- writeFileSync3(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1040
+ mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1041
+ writeFileSync4(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
916
1042
  }
917
1043
  };
918
1044
 
919
1045
  // src/lib/receipt-archive.ts
920
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync5, unlinkSync as unlinkSync4 } from "fs";
1046
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6, unlinkSync as unlinkSync5 } from "fs";
921
1047
  import { homedir as homedir4 } from "os";
922
- import { dirname as dirname4, join as join5 } from "path";
1048
+ import { dirname as dirname5, join as join6 } from "path";
923
1049
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes4 } from "crypto";
924
- var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ?? join5(homedir4(), ".suveren");
1050
+ var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ?? join6(homedir4(), ".suveren");
925
1051
  function stripPreviews(proposal) {
926
1052
  const args = proposal.toolArgs;
927
1053
  if (!args || typeof args !== "object") return proposal;
@@ -935,7 +1061,7 @@ var ReceiptArchive = class {
935
1061
  vaultKey = null;
936
1062
  constructor(filePath) {
937
1063
  if (filePath && filePath.endsWith(".json")) {
938
- this.baseDir = dirname4(filePath);
1064
+ this.baseDir = dirname5(filePath);
939
1065
  } else {
940
1066
  this.baseDir = filePath ?? DEFAULT_DIR4;
941
1067
  }
@@ -946,13 +1072,13 @@ var ReceiptArchive = class {
946
1072
  */
947
1073
  setVaultKey(key) {
948
1074
  this.vaultKey = key;
949
- if (existsSync5(this.encryptedFilePath)) {
1075
+ if (existsSync6(this.encryptedFilePath)) {
950
1076
  this.loadEncrypted();
951
1077
  } else if (this.data.receipts.length > 0 || Object.keys(this.data.authorizations).length > 0) {
952
1078
  this.persistEncrypted();
953
- if (existsSync5(this.plaintextFilePath)) {
1079
+ if (existsSync6(this.plaintextFilePath)) {
954
1080
  try {
955
- unlinkSync4(this.plaintextFilePath);
1081
+ unlinkSync5(this.plaintextFilePath);
956
1082
  } catch {
957
1083
  }
958
1084
  }
@@ -964,7 +1090,7 @@ var ReceiptArchive = class {
964
1090
  * this state — that would report a hollow success over unreadable evidence.
965
1091
  */
966
1092
  isLocked() {
967
- return this.vaultKey === null && existsSync5(this.encryptedFilePath);
1093
+ return this.vaultKey === null && existsSync6(this.encryptedFilePath);
968
1094
  }
969
1095
  /**
970
1096
  * Archive a signed receipt (and the grant it was issued under).
@@ -1065,19 +1191,19 @@ var ReceiptArchive = class {
1065
1191
  }
1066
1192
  // ─── File paths ─────────────────────────────────────────────────────────
1067
1193
  get plaintextFilePath() {
1068
- return join5(this.baseDir, "receipt-archive.json");
1194
+ return join6(this.baseDir, "receipt-archive.json");
1069
1195
  }
1070
1196
  get encryptedFilePath() {
1071
- return join5(this.baseDir, "receipt-archive.enc.json");
1197
+ return join6(this.baseDir, "receipt-archive.enc.json");
1072
1198
  }
1073
1199
  // ─── Load / Persist ─────────────────────────────────────────────────────
1074
1200
  loadPlaintext() {
1075
- if (!existsSync5(this.plaintextFilePath)) {
1076
- mkdirSync4(this.baseDir, { recursive: true });
1201
+ if (!existsSync6(this.plaintextFilePath)) {
1202
+ mkdirSync5(this.baseDir, { recursive: true });
1077
1203
  return;
1078
1204
  }
1079
1205
  try {
1080
- const raw = readFileSync5(this.plaintextFilePath, "utf-8");
1206
+ const raw = readFileSync6(this.plaintextFilePath, "utf-8");
1081
1207
  const parsed = JSON.parse(raw);
1082
1208
  this.data = {
1083
1209
  version: 1,
@@ -1087,18 +1213,18 @@ var ReceiptArchive = class {
1087
1213
  } catch {
1088
1214
  console.error(`[ReceiptArchive] Could not parse ${this.plaintextFilePath} \u2014 preserving as .corrupt`);
1089
1215
  try {
1090
- writeFileSync4(
1216
+ writeFileSync5(
1091
1217
  `${this.plaintextFilePath}.corrupt-${Date.now()}`,
1092
- readFileSync5(this.plaintextFilePath)
1218
+ readFileSync6(this.plaintextFilePath)
1093
1219
  );
1094
1220
  } catch {
1095
1221
  }
1096
1222
  }
1097
1223
  }
1098
1224
  loadEncrypted() {
1099
- if (!existsSync5(this.encryptedFilePath)) return;
1225
+ if (!existsSync6(this.encryptedFilePath)) return;
1100
1226
  try {
1101
- const raw = readFileSync5(this.encryptedFilePath, "utf-8");
1227
+ const raw = readFileSync6(this.encryptedFilePath, "utf-8");
1102
1228
  const data = JSON.parse(raw);
1103
1229
  const decrypted = this.decrypt(data.blob);
1104
1230
  const parsed = JSON.parse(decrypted);
@@ -1110,9 +1236,9 @@ var ReceiptArchive = class {
1110
1236
  } catch (err) {
1111
1237
  console.error(`[ReceiptArchive] Could not decrypt ${this.encryptedFilePath} \u2014 preserving as .corrupt:`, err);
1112
1238
  try {
1113
- writeFileSync4(
1239
+ writeFileSync5(
1114
1240
  `${this.encryptedFilePath}.corrupt-${Date.now()}`,
1115
- readFileSync5(this.encryptedFilePath)
1241
+ readFileSync6(this.encryptedFilePath)
1116
1242
  );
1117
1243
  } catch {
1118
1244
  }
@@ -1126,29 +1252,29 @@ var ReceiptArchive = class {
1126
1252
  }
1127
1253
  }
1128
1254
  persistPlaintext() {
1129
- mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1130
- writeFileSync4(this.plaintextFilePath, JSON.stringify(this.data, null, 2), { encoding: "utf-8", mode: 384 });
1255
+ mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1256
+ writeFileSync5(this.plaintextFilePath, JSON.stringify(this.data, null, 2), { encoding: "utf-8", mode: 384 });
1131
1257
  }
1132
1258
  persistEncrypted() {
1133
1259
  const data = {
1134
1260
  version: 1,
1135
1261
  blob: this.encrypt(JSON.stringify(this.data))
1136
1262
  };
1137
- mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1138
- writeFileSync4(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1263
+ mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1264
+ writeFileSync5(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1139
1265
  }
1140
1266
  };
1141
1267
 
1142
1268
  // src/lib/execution-journal.ts
1143
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync6, renameSync } from "fs";
1269
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync7, renameSync } from "fs";
1144
1270
  import { homedir as homedir5 } from "os";
1145
- import { dirname as dirname5, join as join6 } from "path";
1146
- import { createHash } from "crypto";
1147
- var DEFAULT_DIR5 = process.env.SUVEREN_DATA_DIR ?? join6(homedir5(), ".suveren");
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");
1148
1274
  var FILE_NAME = "execution-journal.json";
1149
1275
  var MAX_AGE_SECONDS2 = 90 * 24 * 60 * 60;
1150
1276
  function hashToolArgs(args) {
1151
- return "sha256:" + createHash("sha256").update(stableStringify(args)).digest("hex");
1277
+ return "sha256:" + createHash2("sha256").update(stableStringify(args)).digest("hex");
1152
1278
  }
1153
1279
  function stableStringify(value) {
1154
1280
  if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
@@ -1160,8 +1286,8 @@ function stableStringify(value) {
1160
1286
  var ExecutionJournal = class {
1161
1287
  filePath;
1162
1288
  constructor(filePath) {
1163
- const baseDir = filePath && filePath.endsWith(".json") ? dirname5(filePath) : filePath ?? DEFAULT_DIR5;
1164
- this.filePath = join6(baseDir, FILE_NAME);
1289
+ const baseDir = filePath && filePath.endsWith(".json") ? dirname6(filePath) : filePath ?? DEFAULT_DIR5;
1290
+ this.filePath = join7(baseDir, FILE_NAME);
1165
1291
  }
1166
1292
  /** Look a ticket up. Always reads from disk — another process may have written. */
1167
1293
  get(ticketId) {
@@ -1200,9 +1326,9 @@ var ExecutionJournal = class {
1200
1326
  }
1201
1327
  // ─── Persistence ────────────────────────────────────────────────────────
1202
1328
  load() {
1203
- if (!existsSync6(this.filePath)) return { version: 1, entries: [] };
1329
+ if (!existsSync7(this.filePath)) return { version: 1, entries: [] };
1204
1330
  try {
1205
- const parsed = JSON.parse(readFileSync6(this.filePath, "utf8"));
1331
+ const parsed = JSON.parse(readFileSync7(this.filePath, "utf8"));
1206
1332
  if (parsed?.version !== 1 || !Array.isArray(parsed.entries)) {
1207
1333
  throw new Error("unexpected shape");
1208
1334
  }
@@ -1216,9 +1342,9 @@ var ExecutionJournal = class {
1216
1342
  persist(file) {
1217
1343
  const cutoff = nowSec() - MAX_AGE_SECONDS2;
1218
1344
  file.entries = file.entries.filter((e) => e.startedAt >= cutoff);
1219
- mkdirSync5(dirname5(this.filePath), { recursive: true, mode: 448 });
1345
+ mkdirSync6(dirname6(this.filePath), { recursive: true, mode: 448 });
1220
1346
  const tmp = this.filePath + ".tmp";
1221
- writeFileSync5(tmp, JSON.stringify(file, null, 2), { mode: 384 });
1347
+ writeFileSync6(tmp, JSON.stringify(file, null, 2), { mode: 384 });
1222
1348
  renameSync(tmp, this.filePath);
1223
1349
  }
1224
1350
  };
@@ -1226,6 +1352,61 @@ function nowSec() {
1226
1352
  return Math.floor(Date.now() / 1e3);
1227
1353
  }
1228
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
+
1229
1410
  // src/lib/gatekeeper.ts
1230
1411
  import { verify } from "@hap/core";
1231
1412
  var MCPGatekeeper = class {
@@ -1276,7 +1457,26 @@ var MCPGatekeeper = class {
1276
1457
  authorization: auth
1277
1458
  };
1278
1459
  }
1279
- const publicKeyHex = await this.cache.getPublicKey();
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
+ }
1280
1480
  const resolvedBounds = override?.bounds ?? auth.bounds ?? auth.frame;
1281
1481
  const resolvedContext = override?.context ?? auth.context;
1282
1482
  const frame = { ...resolvedBounds, profile: auth.profileId };
@@ -1308,15 +1508,25 @@ var SharedState = class {
1308
1508
  receiptArchive;
1309
1509
  /** Which tickets this Gatekeeper has executed — the "one execution per ticket" half of exactly-once. */
1310
1510
  executionJournal;
1511
+ /** What THIS gateway submitted for each review-mode proposal it created —
1512
+ * see ticket-verify.ts / commitments.ts. */
1513
+ proposalSubmissions;
1311
1514
  gatekeeper;
1312
- constructor(spUrl2, gateStorePath) {
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) {
1313
1522
  this.spClient = new SPClient(spUrl2);
1314
- this.cache = new AttestationCache(this.spClient);
1523
+ this.cache = new AttestationCache(this.spClient, dataDir2);
1315
1524
  this.gateStore = new GateStore(gateStorePath);
1316
1525
  this.executionLog = new ExecutionLog(gateStorePath);
1317
1526
  this.denialLog = new DenialLog(gateStorePath);
1318
1527
  this.receiptArchive = new ReceiptArchive(gateStorePath);
1319
1528
  this.executionJournal = new ExecutionJournal(gateStorePath);
1529
+ this.proposalSubmissions = new ProposalSubmissionStore(gateStorePath);
1320
1530
  this.gatekeeper = new MCPGatekeeper(this.cache);
1321
1531
  }
1322
1532
  /**
@@ -1332,7 +1542,8 @@ var SharedState = class {
1332
1542
  let asPublicKey;
1333
1543
  try {
1334
1544
  asPublicKey = await this.cache.getPublicKey();
1335
- } catch {
1545
+ } catch (err) {
1546
+ if (err instanceof AsKeyMismatchError) throw err;
1336
1547
  }
1337
1548
  this.receiptArchive.record({
1338
1549
  receipt,
@@ -1354,6 +1565,7 @@ var SharedState = class {
1354
1565
  } : void 0
1355
1566
  });
1356
1567
  } catch (err) {
1568
+ if (err instanceof AsKeyMismatchError) throw err;
1357
1569
  console.error(
1358
1570
  "[Suveren MCP] Receipt archive write failed (execution proceeds \u2014 AS retains authoritative copy):",
1359
1571
  err
@@ -1402,6 +1614,7 @@ import { z } from "zod";
1402
1614
  import { getProfile } from "@hap/core";
1403
1615
 
1404
1616
  // src/lib/consumption.ts
1617
+ import { boundActionTypes } from "@hap/core";
1405
1618
  function getConsumptionState(auth, executionLog, profile) {
1406
1619
  if (!profile?.boundsSchema?.fields) return [];
1407
1620
  const entries = [];
@@ -1421,7 +1634,8 @@ function getConsumptionState(auth, executionLog, profile) {
1421
1634
  auth.path,
1422
1635
  cumulativeField,
1423
1636
  bt.window,
1424
- now
1637
+ now,
1638
+ boundActionTypes(fieldName, fieldDef)
1425
1639
  );
1426
1640
  entries.push({
1427
1641
  // displayName FIRST: description is prose meant for a human reading the
@@ -1465,24 +1679,24 @@ function formatConsumptionFull(entries) {
1465
1679
  }
1466
1680
 
1467
1681
  // src/lib/context-loader.ts
1468
- import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
1469
- import { homedir as homedir6 } from "os";
1470
- import { join as join7 } from "path";
1471
- var DEFAULT_DIR6 = process.env.SUVEREN_DATA_DIR ?? join7(homedir6(), ".suveren");
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");
1472
1686
  var BRIEF_MAX_CHARS = 16 * 1024;
1473
- function readContextFile(dataDir) {
1474
- const dir = dataDir ?? DEFAULT_DIR6;
1475
- const filePath = join7(dir, "context.md");
1476
- if (!existsSync7(filePath)) return null;
1687
+ function readContextFile(dataDir2) {
1688
+ const dir = dataDir2 ?? DEFAULT_DIR7;
1689
+ const filePath = join9(dir, "context.md");
1690
+ if (!existsSync9(filePath)) return null;
1477
1691
  try {
1478
- const content = readFileSync7(filePath, "utf-8").trim();
1692
+ const content = readFileSync9(filePath, "utf-8").trim();
1479
1693
  return content || null;
1480
1694
  } catch {
1481
1695
  return null;
1482
1696
  }
1483
1697
  }
1484
- function getContextForBrief(dataDir) {
1485
- const full = readContextFile(dataDir);
1698
+ function getContextForBrief(dataDir2) {
1699
+ const full = readContextFile(dataDir2);
1486
1700
  if (!full) return { brief: null, truncated: false };
1487
1701
  if (full.length <= BRIEF_MAX_CHARS) {
1488
1702
  return { brief: full, truncated: false };
@@ -1578,14 +1792,41 @@ function uiUrl() {
1578
1792
  const port2 = process.env.SUVEREN_CP_PORT ?? "3400";
1579
1793
  return `http://localhost:${port2}`;
1580
1794
  }
1581
- function lockedNotice(action) {
1582
- const what = action ? `Cannot ${action}: the` : "The";
1583
- return `${what} Suveren gateway is running but LOCKED, so it cannot read any authorizations or credentials.
1795
+ function bootLockedNotice(what) {
1796
+ return `${what} Suveren gateway is running but LOCKED, so it cannot read any mandates or credentials.
1584
1797
 
1585
- This is not the same as having no authorizations \u2014 yours are on disk, encrypted, and unreadable until someone unlocks them.
1798
+ This is not the same as having no mandates \u2014 yours are on disk, encrypted, and unreadable until someone unlocks them.
1586
1799
 
1587
1800
  TELL THE USER: open ${uiUrl()} and enter your Suveren API key to unlock the gateway. It boots locked by design after every restart; the key is never stored.`;
1588
1801
  }
1802
+ function expiredSessionNotice(what) {
1803
+ return `${what} Suveren gateway's sign-in has ended (sign-ins last 30 days, or it was revoked), so it is now LOCKED.
1804
+
1805
+ TELL THE USER: open ${uiUrl()} and enter your Suveren API key to sign in again. Your mandates are safe; nothing ran.`;
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
+ }
1817
+ function lockedNotice(action, reason = "restart") {
1818
+ const what = action ? `Cannot ${action}: the` : "The";
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
+ }
1829
+ }
1589
1830
 
1590
1831
  // src/tools/authorizations.ts
1591
1832
  import { getProfile as getProfile4 } from "@hap/core";
@@ -1593,6 +1834,9 @@ import { getProfile as getProfile4 } from "@hap/core";
1593
1834
  // src/lib/receipt-footer.ts
1594
1835
  import { deriveIdentityLine } from "@hap/core";
1595
1836
  var AS_BASE = (process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai").replace(/\/$/, "");
1837
+ function setAsBaseUrl(url) {
1838
+ AS_BASE = url.replace(/\/$/, "");
1839
+ }
1596
1840
  var OPERATOR_NAME = process.env.SUVEREN_OPERATOR_NAME ?? "Suveren";
1597
1841
  var HAP_URL = "https://www.humanagencyprotocol.org/";
1598
1842
  var FOOTER_PROFILES = /* @__PURE__ */ new Set(["email", "calendar", "publish"]);
@@ -1698,6 +1942,83 @@ function attachReceiptId(tool, args, receiptId) {
1698
1942
  return { ...args, receipt_id: receiptId };
1699
1943
  }
1700
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
+
1701
2022
  // src/lib/arg-encoding.ts
1702
2023
  function rfc2047Encode(value) {
1703
2024
  if (!/[^\x00-\x7F]/.test(value)) return value;
@@ -2109,7 +2430,7 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
2109
2430
  const lockedGuard = (inner) => async (args) => {
2110
2431
  if (!state2.spClient.isUnlocked()) {
2111
2432
  return {
2112
- content: [{ type: "text", text: lockedNotice(`use ${tool.namespacedName}`) }],
2433
+ content: [{ type: "text", text: lockedNotice(`use ${tool.namespacedName}`, state2.spClient.getLockReason() ?? "restart") }],
2113
2434
  isError: true
2114
2435
  };
2115
2436
  }
@@ -2413,6 +2734,14 @@ function createGatedToolHandlerInner(tool, integrationManager2, state2) {
2413
2734
  toolArgs: enrichedArgs,
2414
2735
  executionContext: { ...execution }
2415
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
+ });
2416
2745
  return {
2417
2746
  content: [{
2418
2747
  type: "text",
@@ -2421,6 +2750,12 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
2421
2750
  }]
2422
2751
  };
2423
2752
  } catch (err) {
2753
+ if (!state2.spClient.isUnlocked()) {
2754
+ return {
2755
+ content: [{ type: "text", text: lockedNotice(`use ${tool.namespacedName}`, "expired") }],
2756
+ isError: true
2757
+ };
2758
+ }
2424
2759
  return {
2425
2760
  content: [{ type: "text", text: `Failed to submit proposal: ${err instanceof Error ? err.message : String(err)}` }],
2426
2761
  isError: true
@@ -2449,6 +2784,14 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
2449
2784
  ...binding ? { contentHash: binding.contentHash, contentBinding: binding.contentBinding } : {}
2450
2785
  });
2451
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
+ });
2452
2795
  await state2.archiveReceipt(receipt, {
2453
2796
  authorizationId: authzId,
2454
2797
  profileId: auth.profileId,
@@ -2463,6 +2806,13 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
2463
2806
  boundContent: binding?.boundContent
2464
2807
  });
2465
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
+ }
2466
2816
  if (err instanceof ContentBindingError) {
2467
2817
  return {
2468
2818
  content: [{
@@ -2508,6 +2858,14 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
2508
2858
  executionContext: { ...execution },
2509
2859
  pendingApprovers: uniqueApprovers
2510
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
+ });
2511
2869
  return {
2512
2870
  content: [{
2513
2871
  type: "text",
@@ -2516,6 +2874,12 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.`
2516
2874
  }]
2517
2875
  };
2518
2876
  } catch (proposalErr) {
2877
+ if (!state2.spClient.isUnlocked()) {
2878
+ return {
2879
+ content: [{ type: "text", text: lockedNotice(`use ${tool.namespacedName}`, "expired") }],
2880
+ isError: true
2881
+ };
2882
+ }
2519
2883
  return {
2520
2884
  content: [{ type: "text", text: `Failed to submit approval proposal: ${proposalErr instanceof Error ? proposalErr.message : String(proposalErr)}` }],
2521
2885
  isError: true
@@ -2537,6 +2901,12 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.`
2537
2901
  isError: true
2538
2902
  };
2539
2903
  }
2904
+ if (!state2.spClient.isUnlocked()) {
2905
+ return {
2906
+ content: [{ type: "text", text: lockedNotice(`use ${tool.namespacedName}`, "expired") }],
2907
+ isError: true
2908
+ };
2909
+ }
2540
2910
  return {
2541
2911
  content: [{ type: "text", text: `SP unavailable \u2014 tool call blocked. ${err instanceof Error ? err.message : ""}` }],
2542
2912
  isError: true
@@ -2667,7 +3037,7 @@ function buildCapabilityMap(profileId, toolGating, integrationManager2) {
2667
3037
  function listAuthorizationsHandler(state2, integrationManager2, contextDir) {
2668
3038
  return async (args) => {
2669
3039
  if (!state2.spClient.isUnlocked()) {
2670
- return { content: [{ type: "text", text: lockedNotice("list authorizations") }] };
3040
+ return { content: [{ type: "text", text: lockedNotice("list authorizations", state2.spClient.getLockReason() ?? "restart") }] };
2671
3041
  }
2672
3042
  const authorizations = state2.getEnrichedAuthorizations();
2673
3043
  const now = Math.floor(Date.now() / 1e3);
@@ -2861,7 +3231,7 @@ function shortProfileName3(profileId) {
2861
3231
  function listIntegrationsHandler(state2, integrationManager2) {
2862
3232
  return async () => {
2863
3233
  if (!state2.spClient.isUnlocked()) {
2864
- return { content: [{ type: "text", text: lockedNotice("list integrations") }] };
3234
+ return { content: [{ type: "text", text: lockedNotice("list integrations", state2.spClient.getLockReason() ?? "restart") }] };
2865
3235
  }
2866
3236
  if (!integrationManager2) {
2867
3237
  return { content: [{ type: "text", text: "No integration manager available." }] };
@@ -2903,6 +3273,9 @@ function listIntegrationsHandler(state2, integrationManager2) {
2903
3273
 
2904
3274
  // src/tools/commitments.ts
2905
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
+ }
2906
3279
  var installedExecutor = null;
2907
3280
  function installCommittedExecutor(executor) {
2908
3281
  installedExecutor = executor;
@@ -2928,6 +3301,28 @@ async function executeCommitted(proposal, state2, integrationManager2) {
2928
3301
  );
2929
3302
  }
2930
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
+ }
2931
3326
  let receiptId;
2932
3327
  let replayed = false;
2933
3328
  try {
@@ -2963,6 +3358,15 @@ async function executeCommitted(proposal, state2, integrationManager2) {
2963
3358
  });
2964
3359
  receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
2965
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
+ });
2966
3370
  await state2.archiveReceipt(receipt, {
2967
3371
  authorizationId: proposal.authorizationId,
2968
3372
  profileId: proposal.profileId,
@@ -2977,6 +3381,13 @@ async function executeCommitted(proposal, state2, integrationManager2) {
2977
3381
  boundContent: binding?.boundContent
2978
3382
  });
2979
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
+ }
2980
3391
  if (err instanceof ContentBindingError2) {
2981
3392
  return {
2982
3393
  text: `Proposal ${proposal.id}: blocked \u2014 the approved content cannot be bound to the receipt. ${err.message}`,
@@ -3067,7 +3478,7 @@ Result: ${resultText}` };
3067
3478
  function checkPendingCommitmentsHandler(state2, integrationManager2) {
3068
3479
  return async (args) => {
3069
3480
  if (!state2.spClient.isUnlocked()) {
3070
- return { content: [{ type: "text", text: lockedNotice("check commitments") }] };
3481
+ return { content: [{ type: "text", text: lockedNotice("check commitments", state2.spClient.getLockReason() ?? "restart") }] };
3071
3482
  }
3072
3483
  try {
3073
3484
  if (args.proposal_id) {
@@ -3136,9 +3547,13 @@ Wait for the human to approve; do not re-submit the tool call.`
3136
3547
  }]
3137
3548
  };
3138
3549
  }
3139
- const lines = committed.map(
3140
- (p) => `${p.id}: tool=${p.tool}, status=${p.status}, committed=[${Object.keys(p.committedBy).join(",")}]`
3141
- );
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
+ });
3142
3557
  return {
3143
3558
  content: [{
3144
3559
  type: "text",
@@ -3335,16 +3750,16 @@ function verifyGateContentHashes(content, auth) {
3335
3750
  }
3336
3751
 
3337
3752
  // src/lib/integration-registry.ts
3338
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8 } from "fs";
3339
- import { homedir as homedir7 } from "os";
3340
- import { dirname as dirname6, join as join8 } from "path";
3341
- var DEFAULT_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join8(homedir7(), ".suveren");
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");
3342
3757
  var IntegrationRegistry = class {
3343
3758
  integrations = /* @__PURE__ */ new Map();
3344
3759
  filePath;
3345
- constructor(dataDir) {
3346
- const dir = dataDir ?? DEFAULT_DATA_DIR;
3347
- this.filePath = join8(dir, "integrations.json");
3760
+ constructor(dataDir2) {
3761
+ const dir = dataDir2 ?? DEFAULT_DATA_DIR;
3762
+ this.filePath = join10(dir, "integrations.json");
3348
3763
  this.load();
3349
3764
  }
3350
3765
  // ─── CRUD ───────────────────────────────────────────────────────────────
@@ -3375,12 +3790,12 @@ var IntegrationRegistry = class {
3375
3790
  }
3376
3791
  // ─── Load / Save ────────────────────────────────────────────────────────
3377
3792
  load() {
3378
- if (!existsSync8(this.filePath)) {
3379
- mkdirSync6(dirname6(this.filePath), { recursive: true });
3793
+ if (!existsSync10(this.filePath)) {
3794
+ mkdirSync8(dirname8(this.filePath), { recursive: true });
3380
3795
  return;
3381
3796
  }
3382
3797
  try {
3383
- const raw = readFileSync8(this.filePath, "utf-8");
3798
+ const raw = readFileSync10(this.filePath, "utf-8");
3384
3799
  const data = JSON.parse(raw);
3385
3800
  const migrated = data.integrations.map((i) => {
3386
3801
  if ("toolGating" in i && !("profile" in i)) {
@@ -3409,45 +3824,45 @@ var IntegrationRegistry = class {
3409
3824
  version: 1,
3410
3825
  integrations: Array.from(this.integrations.values())
3411
3826
  };
3412
- mkdirSync6(dirname6(this.filePath), { recursive: true });
3413
- writeFileSync6(this.filePath, JSON.stringify(data, null, 2), { encoding: "utf-8" });
3827
+ mkdirSync8(dirname8(this.filePath), { recursive: true });
3828
+ writeFileSync8(this.filePath, JSON.stringify(data, null, 2), { encoding: "utf-8" });
3414
3829
  }
3415
3830
  };
3416
3831
 
3417
3832
  // src/lib/integration-manager.ts
3418
- import { homedir as homedir8 } from "os";
3419
- import { join as join10, delimiter } from "path";
3420
- import { existsSync as existsSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync10, rmSync } from "fs";
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";
3421
3836
  import { execFile } from "child_process";
3422
3837
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3423
3838
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3424
3839
  import { getProfile as getProfile5 } from "@hap/core";
3425
3840
 
3426
3841
  // src/lib/manifest-loader.ts
3427
- import { readFileSync as readFileSync9, existsSync as existsSync9 } from "fs";
3428
- import { join as join9, resolve } from "path";
3842
+ import { readFileSync as readFileSync11, existsSync as existsSync11 } from "fs";
3843
+ import { join as join11, resolve } from "path";
3429
3844
  var manifests = /* @__PURE__ */ new Map();
3430
3845
  function loadManifests(integrationsDir) {
3431
3846
  const dir = resolve(
3432
- integrationsDir ?? process.env.SUVEREN_MANIFESTS_DIR ?? join9(import.meta.dirname ?? __dirname, "..", "..", "..", "..", "content", "integrations")
3847
+ integrationsDir ?? process.env.SUVEREN_MANIFESTS_DIR ?? join11(import.meta.dirname ?? __dirname, "..", "..", "..", "..", "content", "integrations")
3433
3848
  );
3434
- const indexPath = join9(dir, "index.json");
3435
- if (!existsSync9(indexPath)) {
3849
+ const indexPath = join11(dir, "index.json");
3850
+ if (!existsSync11(indexPath)) {
3436
3851
  console.error(`[ManifestLoader] No index.json found at ${indexPath}, skipping manifest loading`);
3437
3852
  return 0;
3438
3853
  }
3439
3854
  let index;
3440
3855
  try {
3441
- index = JSON.parse(readFileSync9(indexPath, "utf-8"));
3856
+ index = JSON.parse(readFileSync11(indexPath, "utf-8"));
3442
3857
  } catch (err) {
3443
3858
  console.error(`[ManifestLoader] Failed to parse ${indexPath}:`, err);
3444
3859
  return 0;
3445
3860
  }
3446
3861
  let loaded = 0;
3447
3862
  for (const [id, relativePath] of Object.entries(index.integrations)) {
3448
- const manifestPath = join9(dir, relativePath);
3863
+ const manifestPath = join11(dir, relativePath);
3449
3864
  try {
3450
- const manifest = JSON.parse(readFileSync9(manifestPath, "utf-8"));
3865
+ const manifest = JSON.parse(readFileSync11(manifestPath, "utf-8"));
3451
3866
  manifests.set(id, manifest);
3452
3867
  loaded++;
3453
3868
  } catch (err) {
@@ -3535,26 +3950,26 @@ function safeHost(url) {
3535
3950
  }
3536
3951
 
3537
3952
  // src/lib/integration-manager.ts
3538
- var DEFAULT_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join10(homedir8(), ".suveren");
3539
- var INTEGRATIONS_DIR = process.env.SUVEREN_INTEGRATIONS_DIR ?? join10(DEFAULT_DATA_DIR2, "integrations");
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");
3540
3955
  var installLock = Promise.resolve();
3541
3956
  function withInstallLock(task) {
3542
3957
  const run = installLock.then(task, task);
3543
3958
  installLock = run.then(() => void 0, () => void 0);
3544
3959
  return run;
3545
3960
  }
3546
- var INTEGRATIONS_BIN = join10(INTEGRATIONS_DIR, "node_modules", ".bin");
3961
+ var INTEGRATIONS_BIN = join12(INTEGRATIONS_DIR, "node_modules", ".bin");
3547
3962
  function buildPath() {
3548
3963
  const base = process.env.PATH ?? "";
3549
3964
  return [INTEGRATIONS_BIN, base].join(delimiter);
3550
3965
  }
3551
3966
  function ensureIntegrationsDir() {
3552
- if (!existsSync10(INTEGRATIONS_DIR)) {
3553
- mkdirSync7(INTEGRATIONS_DIR, { recursive: true });
3967
+ if (!existsSync12(INTEGRATIONS_DIR)) {
3968
+ mkdirSync9(INTEGRATIONS_DIR, { recursive: true });
3554
3969
  }
3555
- const pkgPath = join10(INTEGRATIONS_DIR, "package.json");
3556
- if (!existsSync10(pkgPath)) {
3557
- writeFileSync7(pkgPath, JSON.stringify({ name: "suveren-integrations", version: "1.0.0", private: true }, null, 2));
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));
3558
3973
  }
3559
3974
  }
3560
3975
  function readAgeOf(config) {
@@ -3620,19 +4035,19 @@ var IntegrationManager = class {
3620
4035
  * exist, and treat anything else as not-installed (and reinstallable).
3621
4036
  */
3622
4037
  isUsableInstall(npmPackage) {
3623
- const pkgDir = join10(INTEGRATIONS_DIR, "node_modules", ...npmPackage.split("/"));
3624
- const pkgJson = join10(pkgDir, "package.json");
3625
- if (!existsSync10(pkgDir) || !existsSync10(pkgJson)) return false;
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;
3626
4041
  try {
3627
- const pkg = JSON.parse(readFileSync10(pkgJson, "utf8"));
4042
+ const pkg = JSON.parse(readFileSync12(pkgJson, "utf8"));
3628
4043
  const defaultBinName = (pkg.name ?? npmPackage).split("/").pop() ?? "";
3629
4044
  const binMap = typeof pkg.bin === "string" ? { [defaultBinName]: pkg.bin } : pkg.bin ?? {};
3630
4045
  const binEntries = Object.entries(binMap);
3631
4046
  for (const [binName, target] of binEntries) {
3632
- if (!existsSync10(join10(pkgDir, target))) return false;
4047
+ if (!existsSync12(join12(pkgDir, target))) return false;
3633
4048
  if (!this.binShimExists(binName)) return false;
3634
4049
  }
3635
- if (binEntries.length === 0 && pkg.main && !existsSync10(join10(pkgDir, pkg.main))) return false;
4050
+ if (binEntries.length === 0 && pkg.main && !existsSync12(join12(pkgDir, pkg.main))) return false;
3636
4051
  return true;
3637
4052
  } catch {
3638
4053
  return false;
@@ -3646,7 +4061,7 @@ var IntegrationManager = class {
3646
4061
  binShimExists(binName) {
3647
4062
  if (!binName) return false;
3648
4063
  const candidates = process.platform === "win32" ? [binName, `${binName}.cmd`, `${binName}.CMD`, `${binName}.ps1`] : [binName];
3649
- return candidates.some((c) => existsSync10(join10(INTEGRATIONS_BIN, c)));
4064
+ return candidates.some((c) => existsSync12(join12(INTEGRATIONS_BIN, c)));
3650
4065
  }
3651
4066
  /**
3652
4067
  * Install an npm package into the managed integrations directory if not
@@ -3670,8 +4085,8 @@ var IntegrationManager = class {
3670
4085
  }
3671
4086
  /** The actual install. Callers MUST hold the install lock. */
3672
4087
  async installNow(npmPackage) {
3673
- const pkgDir = join10(INTEGRATIONS_DIR, "node_modules", ...npmPackage.split("/"));
3674
- if (existsSync10(pkgDir)) {
4088
+ const pkgDir = join12(INTEGRATIONS_DIR, "node_modules", ...npmPackage.split("/"));
4089
+ if (existsSync12(pkgDir)) {
3675
4090
  console.error(`[IntegrationManager] Removing unusable install of ${npmPackage}`);
3676
4091
  try {
3677
4092
  rmSync(pkgDir, { recursive: true, force: true });
@@ -3785,6 +4200,11 @@ var IntegrationManager = class {
3785
4200
  const transport = new StdioClientTransport({
3786
4201
  command: config.command,
3787
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.
3788
4208
  env: {
3789
4209
  ...process.env,
3790
4210
  PATH: buildPath(),
@@ -4101,28 +4521,28 @@ var IntegrationManager = class {
4101
4521
  };
4102
4522
 
4103
4523
  // src/lib/profile-loader.ts
4104
- import { readFileSync as readFileSync11, existsSync as existsSync11 } from "fs";
4105
- import { join as join11, resolve as resolve2 } from "path";
4524
+ import { readFileSync as readFileSync13, existsSync as existsSync13 } from "fs";
4525
+ import { join as join13, resolve as resolve2 } from "path";
4106
4526
  import { registerProfile } from "@hap/core";
4107
4527
  function loadProfiles(profilesDir) {
4108
- const dir = resolve2(profilesDir ?? process.env.SUVEREN_PROFILES_DIR ?? join11(import.meta.dirname ?? __dirname, "..", "..", "..", "..", "..", "hap-profiles"));
4109
- const indexPath = join11(dir, "index.json");
4110
- if (!existsSync11(indexPath)) {
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)) {
4111
4531
  warnNoProfiles(`No index.json at ${indexPath}`);
4112
4532
  return 0;
4113
4533
  }
4114
4534
  let index;
4115
4535
  try {
4116
- index = JSON.parse(readFileSync11(indexPath, "utf-8"));
4536
+ index = JSON.parse(readFileSync13(indexPath, "utf-8"));
4117
4537
  } catch (err) {
4118
4538
  console.error(`[ProfileLoader] Failed to parse ${indexPath}:`, err);
4119
4539
  return 0;
4120
4540
  }
4121
4541
  let loaded = 0;
4122
4542
  for (const [profileId, relativePath] of Object.entries(index.profiles)) {
4123
- const profilePath = join11(dir, relativePath);
4543
+ const profilePath = join13(dir, relativePath);
4124
4544
  try {
4125
- const profile = JSON.parse(readFileSync11(profilePath, "utf-8"));
4545
+ const profile = JSON.parse(readFileSync13(profilePath, "utf-8"));
4126
4546
  registerProfile(profileId, profile);
4127
4547
  const shortName = profileId.split("/").pop()?.replace(/@.*$/, "");
4128
4548
  if (shortName && shortName !== profileId) {
@@ -4158,8 +4578,8 @@ function warnNoProfiles(reason) {
4158
4578
  import { decodeAttestationBlob as decodeAttestationBlob3 } from "@hap/core";
4159
4579
 
4160
4580
  // src/lib/committed-executor.ts
4161
- import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync8 } from "fs";
4162
- import { dirname as dirname7, join as join12 } from "path";
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";
4163
4583
  var CommittedExecutor = class {
4164
4584
  constructor(run) {
4165
4585
  this.run = run;
@@ -4186,8 +4606,8 @@ var CommittedExecutor = class {
4186
4606
  var ExecutorLock = class {
4187
4607
  path;
4188
4608
  held = false;
4189
- constructor(dataDir) {
4190
- this.path = join12(dataDir, "executor.lock");
4609
+ constructor(dataDir2) {
4610
+ this.path = join14(dataDir2, "executor.lock");
4191
4611
  }
4192
4612
  /** Try to take the lock. Returns the holder's pid when someone else has it. */
4193
4613
  acquire() {
@@ -4195,9 +4615,9 @@ var ExecutorLock = class {
4195
4615
  if (current && current.pid !== process.pid && isAlive(current.pid)) {
4196
4616
  return { held: false, holderPid: current.pid };
4197
4617
  }
4198
- mkdirSync8(dirname7(this.path), { recursive: true, mode: 448 });
4618
+ mkdirSync10(dirname9(this.path), { recursive: true, mode: 448 });
4199
4619
  const lock = { pid: process.pid, startedAt: Math.floor(Date.now() / 1e3) };
4200
- writeFileSync8(this.path, JSON.stringify(lock), { mode: 384 });
4620
+ writeFileSync10(this.path, JSON.stringify(lock), { mode: 384 });
4201
4621
  this.held = true;
4202
4622
  return { held: true };
4203
4623
  }
@@ -4213,15 +4633,15 @@ var ExecutorLock = class {
4213
4633
  const current = this.read();
4214
4634
  if (current?.pid === process.pid) {
4215
4635
  try {
4216
- unlinkSync5(this.path);
4636
+ unlinkSync6(this.path);
4217
4637
  } catch {
4218
4638
  }
4219
4639
  }
4220
4640
  }
4221
4641
  read() {
4222
- if (!existsSync12(this.path)) return null;
4642
+ if (!existsSync14(this.path)) return null;
4223
4643
  try {
4224
- const parsed = JSON.parse(readFileSync12(this.path, "utf8"));
4644
+ const parsed = JSON.parse(readFileSync14(this.path, "utf8"));
4225
4645
  return typeof parsed?.pid === "number" ? parsed : null;
4226
4646
  } catch {
4227
4647
  return null;
@@ -4238,11 +4658,115 @@ function isAlive(pid) {
4238
4658
  }
4239
4659
 
4240
4660
  // bin/http.ts
4241
- import { homedir as homedir9 } from "os";
4242
- import { join as join13 } from "path";
4243
- var spUrl = process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai";
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);
4244
4757
  var port = parseInt(process.env.SUVEREN_MCP_PORT ?? "3430", 10);
4245
- var state = new SharedState(spUrl);
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
+ })();
4246
4770
  var spApiKey = process.env.SUVEREN_AS_API_KEY ?? "";
4247
4771
  if (spApiKey) {
4248
4772
  state.spClient.setApiKey(spApiKey);
@@ -4312,6 +4836,13 @@ app.post("/internal/configure", internalOnly, (req, res) => {
4312
4836
  }
4313
4837
  res.json({ ok: true });
4314
4838
  });
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"})`);
4844
+ res.json({ ok: true });
4845
+ });
4315
4846
  app.post("/internal/gate-content", internalOnly, async (req, res) => {
4316
4847
  try {
4317
4848
  const { authorizationId, boundsHash, contextHash, context, contextLabels, path: rawPath, gateContent } = req.body;
@@ -4601,6 +5132,15 @@ app.get("/internal/authorizations", internalOnly, (_req, res) => {
4601
5132
  app.get("/internal/manifests", internalOnly, (_req, res) => {
4602
5133
  res.json({ manifests: getAllManifests() });
4603
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
+ });
4604
5144
  app.get("/internal/evidence", internalOnly, (_req, res) => {
4605
5145
  if (state.receiptArchive.isLocked()) {
4606
5146
  res.status(503).json({ error: "Vault locked \u2014 the evidence archive is encrypted until sign-in." });
@@ -4734,12 +5274,12 @@ app.listen(port, "0.0.0.0", () => {
4734
5274
  (proposal) => executeCommitted(proposal, state, integrationManager)
4735
5275
  );
4736
5276
  installCommittedExecutor(committedExecutor);
4737
- const dataDir = process.env.SUVEREN_DATA_DIR ?? join13(homedir9(), ".suveren");
4738
- const executorLock = new ExecutorLock(dataDir);
5277
+ const dataDir2 = process.env.SUVEREN_DATA_DIR ?? join17(homedir10(), ".suveren");
5278
+ const executorLock = new ExecutorLock(dataDir2);
4739
5279
  const lock = executorLock.acquire();
4740
5280
  if (!lock.held) {
4741
5281
  console.error(
4742
- `[Suveren MCP] Committed-proposal execution is DISABLED in this process: pid ${lock.holderPid} holds ${dataDir}/executor.lock. Approved proposals will run there. Stop that gateway if this one should execute.`
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.`
4743
5283
  );
4744
5284
  }
4745
5285
  for (const sig of ["SIGINT", "SIGTERM", "exit"]) {