@suveren/gateway 0.3.16 → 0.4.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 (256) hide show
  1. package/bin/suveren-gateway.js +419 -28
  2. package/content/integrations/calendar.json +20 -8
  3. package/content/integrations/crm.json +97 -23
  4. package/content/integrations/gmail.json +166 -29
  5. package/content/integrations/linkedin.json +15 -3
  6. package/content/integrations/mollie.json +2 -2
  7. package/dist/control-plane/index.mjs +333 -41
  8. package/dist/mcp-server/http.mjs +882 -212
  9. package/dist/ui/assets/index-BDQY7Z3H.js +105 -0
  10. package/dist/ui/assets/{index-DOt3SNnl.css → index-JHaCddDE.css} +1 -1
  11. package/dist/ui/index.html +2 -2
  12. package/node_modules/@hap/core/dist/index.d.mts +34 -2
  13. package/node_modules/@hap/core/dist/index.d.ts +34 -2
  14. package/node_modules/@hap/core/dist/index.js +15 -3
  15. package/node_modules/@hap/core/dist/index.mjs +15 -3
  16. package/node_modules/@hap/core/package.json +1 -1
  17. package/node_modules/@hap/core/src/gatekeeper.ts +47 -1
  18. package/node_modules/@hap/core/src/identity.ts +9 -4
  19. package/node_modules/@hap/core/src/types.ts +27 -0
  20. package/node_modules/@hono/node-server/README.md +58 -25
  21. package/node_modules/@hono/node-server/dist/conninfo.cjs +22 -0
  22. package/node_modules/@hono/node-server/dist/{conninfo.d.ts → conninfo.d.cts} +4 -3
  23. package/node_modules/@hono/node-server/dist/conninfo.d.mts +4 -3
  24. package/node_modules/@hono/node-server/dist/conninfo.mjs +19 -16
  25. package/node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs +5 -0
  26. package/node_modules/@hono/node-server/dist/constants-BXAKTxRC.cjs +11 -0
  27. package/node_modules/@hono/node-server/dist/index.cjs +1173 -0
  28. package/node_modules/@hono/node-server/dist/index.d.cts +101 -0
  29. package/node_modules/@hono/node-server/dist/index.d.mts +101 -8
  30. package/node_modules/@hono/node-server/dist/index.mjs +1143 -637
  31. package/node_modules/@hono/node-server/dist/serve-static.cjs +151 -0
  32. package/node_modules/@hono/node-server/dist/serve-static.d.cts +18 -0
  33. package/node_modules/@hono/node-server/dist/serve-static.d.mts +14 -13
  34. package/node_modules/@hono/node-server/dist/serve-static.mjs +143 -145
  35. package/node_modules/@hono/node-server/dist/utils/response.cjs +8 -0
  36. package/node_modules/@hono/node-server/dist/utils/response.d.cts +4 -0
  37. package/node_modules/@hono/node-server/dist/utils/response.d.mts +3 -2
  38. package/node_modules/@hono/node-server/dist/utils/response.mjs +6 -9
  39. package/node_modules/@hono/node-server/dist/utils/stream.cjs +65 -0
  40. package/node_modules/@hono/node-server/dist/utils/stream.d.cts +6 -0
  41. package/node_modules/@hono/node-server/dist/utils/stream.d.mts +6 -0
  42. package/node_modules/@hono/node-server/dist/utils/stream.mjs +64 -0
  43. package/node_modules/@hono/node-server/package.json +65 -54
  44. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.d.ts.map +1 -1
  45. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js +1 -12
  46. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/index.js.map +1 -1
  47. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts +7 -0
  48. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.d.ts.map +1 -1
  49. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js +9 -3
  50. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/stdio.js.map +1 -1
  51. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.d.ts.map +1 -1
  52. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js +5 -3
  53. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/client/streamableHttp.js.map +1 -1
  54. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.d.ts.map +1 -1
  55. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js +1 -12
  56. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/index.js.map +1 -1
  57. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts +5 -0
  58. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.d.ts.map +1 -0
  59. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js +17 -0
  60. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/sseKeepAlive.js.map +1 -0
  61. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts +9 -1
  62. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.d.ts.map +1 -1
  63. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js +10 -4
  64. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/stdio.js.map +1 -1
  65. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts +21 -0
  66. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.d.ts.map +1 -1
  67. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js +239 -41
  68. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/webStandardStreamableHttp.js.map +1 -1
  69. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.d.ts.map +1 -1
  70. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js +25 -6
  71. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/zod-compat.js.map +1 -1
  72. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts +32 -0
  73. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.d.ts.map +1 -0
  74. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js +64 -0
  75. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/mediaType.js.map +1 -0
  76. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts +5 -0
  77. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.d.ts.map +1 -1
  78. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js +10 -1
  79. package/node_modules/@modelcontextprotocol/sdk/dist/cjs/shared/stdio.js.map +1 -1
  80. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.d.ts.map +1 -1
  81. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js +2 -13
  82. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js.map +1 -1
  83. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts +7 -0
  84. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.d.ts.map +1 -1
  85. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js +9 -3
  86. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js.map +1 -1
  87. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.d.ts.map +1 -1
  88. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js +5 -3
  89. package/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js.map +1 -1
  90. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.d.ts.map +1 -1
  91. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js +2 -13
  92. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js.map +1 -1
  93. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts +5 -0
  94. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.d.ts.map +1 -0
  95. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js +13 -0
  96. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js.map +1 -0
  97. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts +9 -1
  98. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.d.ts.map +1 -1
  99. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js +10 -4
  100. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js.map +1 -1
  101. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts +21 -0
  102. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.d.ts.map +1 -1
  103. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js +239 -41
  104. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js.map +1 -1
  105. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.d.ts.map +1 -1
  106. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js +25 -6
  107. package/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js.map +1 -1
  108. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts +32 -0
  109. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.d.ts.map +1 -0
  110. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js +57 -0
  111. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js.map +1 -0
  112. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts +5 -0
  113. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.d.ts.map +1 -1
  114. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js +9 -0
  115. package/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js.map +1 -1
  116. package/node_modules/@modelcontextprotocol/sdk/node_modules/media-typer/README.md +15 -14
  117. package/node_modules/@modelcontextprotocol/sdk/node_modules/media-typer/index.js +0 -8
  118. package/node_modules/@modelcontextprotocol/sdk/node_modules/media-typer/package.json +16 -12
  119. package/node_modules/@modelcontextprotocol/sdk/package.json +4 -3
  120. package/node_modules/@types/node/README.md +1 -1
  121. package/node_modules/@types/node/crypto.d.ts +1 -1
  122. package/node_modules/@types/node/package.json +2 -2
  123. package/node_modules/body-parser/HISTORY.md +7 -1
  124. package/node_modules/body-parser/lib/types/json.js +7 -3
  125. package/node_modules/body-parser/lib/types/raw.js +7 -3
  126. package/node_modules/body-parser/lib/types/text.js +7 -3
  127. package/node_modules/body-parser/lib/types/urlencoded.js +7 -3
  128. package/node_modules/body-parser/package.json +1 -1
  129. package/node_modules/express-rate-limit/dist/index.cjs +69 -5
  130. package/node_modules/express-rate-limit/dist/index.d.cts +16 -0
  131. package/node_modules/express-rate-limit/dist/index.d.mts +16 -0
  132. package/node_modules/express-rate-limit/dist/index.d.ts +16 -0
  133. package/node_modules/express-rate-limit/dist/index.mjs +55 -5
  134. package/node_modules/express-rate-limit/node_modules/debug/LICENSE +20 -0
  135. package/node_modules/express-rate-limit/node_modules/debug/README.md +481 -0
  136. package/node_modules/express-rate-limit/node_modules/debug/package.json +64 -0
  137. package/node_modules/express-rate-limit/node_modules/debug/src/browser.js +272 -0
  138. package/node_modules/express-rate-limit/node_modules/debug/src/common.js +292 -0
  139. package/node_modules/express-rate-limit/node_modules/debug/src/index.js +10 -0
  140. package/node_modules/express-rate-limit/node_modules/debug/src/node.js +263 -0
  141. package/node_modules/express-rate-limit/node_modules/ms/index.js +162 -0
  142. package/node_modules/express-rate-limit/node_modules/ms/license.md +21 -0
  143. package/node_modules/express-rate-limit/node_modules/ms/package.json +38 -0
  144. package/node_modules/express-rate-limit/node_modules/ms/readme.md +59 -0
  145. package/node_modules/express-rate-limit/package.json +12 -9
  146. package/node_modules/fast-uri/index.js +17 -0
  147. package/node_modules/fast-uri/package.json +1 -1
  148. package/node_modules/fast-uri/test/security.test.js +62 -0
  149. package/node_modules/hono/dist/adapter/aws-lambda/handler.js +1 -4
  150. package/node_modules/hono/dist/adapter/lambda-edge/handler.js +12 -2
  151. package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +1 -4
  152. package/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +12 -2
  153. package/node_modules/hono/dist/cjs/client/client.js +10 -1
  154. package/node_modules/hono/dist/cjs/client/utils.js +1 -1
  155. package/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  156. package/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
  157. package/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
  158. package/node_modules/hono/dist/cjs/middleware/etag/index.js +2 -1
  159. package/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
  160. package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
  161. package/node_modules/hono/dist/cjs/request.js +8 -3
  162. package/node_modules/hono/dist/cjs/router/trie-router/node.js +9 -0
  163. package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  164. package/node_modules/hono/dist/cjs/utils/body.js +6 -0
  165. package/node_modules/hono/dist/cjs/utils/url.js +1 -1
  166. package/node_modules/hono/dist/client/client.js +10 -1
  167. package/node_modules/hono/dist/client/utils.js +1 -1
  168. package/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  169. package/node_modules/hono/dist/middleware/cache/index.js +1 -1
  170. package/node_modules/hono/dist/middleware/compress/index.js +2 -1
  171. package/node_modules/hono/dist/middleware/etag/index.js +2 -1
  172. package/node_modules/hono/dist/middleware/method-override/index.js +5 -3
  173. package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
  174. package/node_modules/hono/dist/request.js +8 -3
  175. package/node_modules/hono/dist/router/trie-router/node.js +9 -0
  176. package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  177. package/node_modules/hono/dist/types/adapter/lambda-edge/handler.d.ts +1 -1
  178. package/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
  179. package/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  180. package/node_modules/hono/dist/types/middleware/language/language.d.ts +18 -0
  181. package/node_modules/hono/dist/types/utils/types.d.ts +1 -1
  182. package/node_modules/hono/dist/utils/accept.js +1 -1
  183. package/node_modules/hono/dist/utils/body.js +6 -0
  184. package/node_modules/hono/dist/utils/url.js +1 -1
  185. package/node_modules/hono/package.json +4 -4
  186. package/node_modules/ip-address/README.md +102 -96
  187. package/node_modules/ip-address/dist/common.d.ts +23 -0
  188. package/node_modules/ip-address/dist/common.js +27 -4
  189. package/node_modules/ip-address/dist/common.js.map +1 -1
  190. package/node_modules/ip-address/dist/ipv4.d.ts +8 -1
  191. package/node_modules/ip-address/dist/ipv4.js +21 -8
  192. package/node_modules/ip-address/dist/ipv4.js.map +1 -1
  193. package/node_modules/ip-address/dist/ipv6.d.ts +59 -1
  194. package/node_modules/ip-address/dist/ipv6.js +149 -41
  195. package/node_modules/ip-address/dist/ipv6.js.map +1 -1
  196. package/node_modules/ip-address/dist/v4/constants.js +5 -1
  197. package/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  198. package/node_modules/ip-address/dist/v6/constants.js +3 -2
  199. package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  200. package/node_modules/ip-address/package.json +2 -2
  201. package/node_modules/jose/README.md +1 -4
  202. package/node_modules/jose/dist/types/jwks/remote.d.ts +3 -3
  203. package/node_modules/jose/dist/webapi/jwks/remote.js +1 -1
  204. package/node_modules/jose/dist/webapi/lib/key_to_jwk.js +4 -1
  205. package/node_modules/jose/package.json +1 -1
  206. package/package.json +2 -2
  207. package/profiles/customers/0.4.profile.json +7 -4
  208. package/profiles/customers/0.5.profile.json +131 -0
  209. package/profiles/customers/0.6.profile.json +153 -0
  210. package/profiles/email/0.4.profile.json +8 -4
  211. package/profiles/index.json +2 -0
  212. package/server.js +10 -0
  213. package/dist/ui/assets/index-CTmWS7W4.js +0 -105
  214. package/node_modules/@hono/node-server/dist/conninfo.js +0 -42
  215. package/node_modules/@hono/node-server/dist/globals.d.mts +0 -2
  216. package/node_modules/@hono/node-server/dist/globals.d.ts +0 -2
  217. package/node_modules/@hono/node-server/dist/globals.js +0 -29
  218. package/node_modules/@hono/node-server/dist/globals.mjs +0 -5
  219. package/node_modules/@hono/node-server/dist/index.d.ts +0 -8
  220. package/node_modules/@hono/node-server/dist/index.js +0 -702
  221. package/node_modules/@hono/node-server/dist/listener.d.mts +0 -13
  222. package/node_modules/@hono/node-server/dist/listener.d.ts +0 -13
  223. package/node_modules/@hono/node-server/dist/listener.js +0 -670
  224. package/node_modules/@hono/node-server/dist/listener.mjs +0 -635
  225. package/node_modules/@hono/node-server/dist/request.d.mts +0 -25
  226. package/node_modules/@hono/node-server/dist/request.d.ts +0 -25
  227. package/node_modules/@hono/node-server/dist/request.js +0 -238
  228. package/node_modules/@hono/node-server/dist/request.mjs +0 -206
  229. package/node_modules/@hono/node-server/dist/response.d.mts +0 -26
  230. package/node_modules/@hono/node-server/dist/response.d.ts +0 -26
  231. package/node_modules/@hono/node-server/dist/response.js +0 -112
  232. package/node_modules/@hono/node-server/dist/response.mjs +0 -85
  233. package/node_modules/@hono/node-server/dist/serve-static.d.ts +0 -17
  234. package/node_modules/@hono/node-server/dist/serve-static.js +0 -177
  235. package/node_modules/@hono/node-server/dist/server.d.mts +0 -10
  236. package/node_modules/@hono/node-server/dist/server.d.ts +0 -10
  237. package/node_modules/@hono/node-server/dist/server.js +0 -696
  238. package/node_modules/@hono/node-server/dist/server.mjs +0 -660
  239. package/node_modules/@hono/node-server/dist/types.d.mts +0 -44
  240. package/node_modules/@hono/node-server/dist/types.d.ts +0 -44
  241. package/node_modules/@hono/node-server/dist/types.js +0 -18
  242. package/node_modules/@hono/node-server/dist/types.mjs +0 -0
  243. package/node_modules/@hono/node-server/dist/utils/response/constants.d.mts +0 -3
  244. package/node_modules/@hono/node-server/dist/utils/response/constants.d.ts +0 -3
  245. package/node_modules/@hono/node-server/dist/utils/response/constants.js +0 -30
  246. package/node_modules/@hono/node-server/dist/utils/response/constants.mjs +0 -5
  247. package/node_modules/@hono/node-server/dist/utils/response.d.ts +0 -3
  248. package/node_modules/@hono/node-server/dist/utils/response.js +0 -37
  249. package/node_modules/@hono/node-server/dist/utils.d.mts +0 -9
  250. package/node_modules/@hono/node-server/dist/utils.d.ts +0 -9
  251. package/node_modules/@hono/node-server/dist/utils.js +0 -99
  252. package/node_modules/@hono/node-server/dist/utils.mjs +0 -71
  253. package/node_modules/@hono/node-server/dist/vercel.d.mts +0 -7
  254. package/node_modules/@hono/node-server/dist/vercel.d.ts +0 -7
  255. package/node_modules/@hono/node-server/dist/vercel.js +0 -677
  256. package/node_modules/@hono/node-server/dist/vercel.mjs +0 -640
@@ -5,8 +5,8 @@ import {
5
5
 
6
6
  // src/index.ts
7
7
  import { randomBytes as randomBytes2 } from "crypto";
8
- import { existsSync as existsSync3, readFileSync as readFileSync3, renameSync } from "fs";
9
- import { join as join3 } from "path";
8
+ import { existsSync as existsSync5, readFileSync as readFileSync4, renameSync } from "fs";
9
+ import { join as join4 } from "path";
10
10
  import { homedir as homedir3 } from "os";
11
11
  import express from "express";
12
12
  import { createProxyMiddleware } from "http-proxy-middleware";
@@ -16,28 +16,64 @@ import { createHash, pbkdf2Sync, randomBytes, createCipheriv, createDecipheriv,
16
16
  import { mkdirSync, readFileSync, writeFileSync, existsSync } from "fs";
17
17
  import { homedir } from "os";
18
18
  import { dirname, join } from "path";
19
+ var KDF_ITERATIONS = 1e5;
20
+ var KDF_KEY_BYTES = 32;
21
+ var ApiKeyUnsealProvider = class {
22
+ constructor(apiKey) {
23
+ this.apiKey = apiKey;
24
+ }
25
+ id = "api-key";
26
+ deriveKey(salt) {
27
+ return pbkdf2Sync(this.apiKey, salt, KDF_ITERATIONS, KDF_KEY_BYTES, "sha256");
28
+ }
29
+ };
19
30
  var Vault = class {
20
31
  vaultKey = null;
21
32
  apiKeyHash = null;
22
33
  spSessionCookie = null;
34
+ unsealedBy = null;
23
35
  dataDir;
24
36
  constructor(dataDir) {
25
37
  this.dataDir = dataDir ?? process.env.SUVEREN_DATA_DIR ?? join(homedir(), ".suveren");
26
38
  }
27
39
  // ─── Key management ─────────────────────────────────────────────────────
28
- deriveAndSetKey(apiKey) {
40
+ /**
41
+ * The vault's PBKDF2 salt, created on first unseal and stable thereafter.
42
+ * Every provider derives against the same salt, so swapping providers on an
43
+ * existing vault produces a different key — which is correct: a vault sealed
44
+ * by one authority is not readable by another.
45
+ */
46
+ ensureSalt() {
29
47
  const vaultData = this.readVaultFile();
30
- let salt;
31
- if (vaultData.salt) {
32
- salt = vaultData.salt;
33
- } else {
34
- salt = randomBytes(32).toString("hex");
35
- vaultData.salt = salt;
48
+ if (!vaultData.salt) {
49
+ vaultData.salt = randomBytes(32).toString("hex");
36
50
  this.writeVaultFile(vaultData);
37
51
  }
38
- this.vaultKey = pbkdf2Sync(apiKey, Buffer.from(salt, "hex"), 1e5, 32, "sha256");
52
+ return Buffer.from(vaultData.salt, "hex");
53
+ }
54
+ /**
55
+ * Unlock the vault using any UnsealProvider. Call sites should prefer this
56
+ * over the API-key-specific helper below; adding an unattended provider then
57
+ * requires no change here.
58
+ */
59
+ async unseal(provider) {
60
+ this.vaultKey = await provider.deriveKey(this.ensureSalt());
61
+ this.unsealedBy = provider.id;
62
+ }
63
+ /**
64
+ * Unlock from the user's API key. Also records the key's hash so subsequent
65
+ * requests can be validated (see validateApiKey) — that check is specific to
66
+ * a user-presented secret and has no meaning for a machine provider, which is
67
+ * why it lives here rather than on the interface.
68
+ */
69
+ async deriveAndSetKey(apiKey) {
70
+ await this.unseal(new ApiKeyUnsealProvider(apiKey));
39
71
  this.apiKeyHash = createHash("sha256").update(apiKey).digest("hex");
40
72
  }
73
+ /** Which provider unlocked this vault, for diagnostics. Null while locked. */
74
+ unsealedByProvider() {
75
+ return this.vaultKey ? this.unsealedBy : null;
76
+ }
41
77
  validateApiKey(apiKey) {
42
78
  if (!this.apiKeyHash) return false;
43
79
  const hash = createHash("sha256").update(apiKey).digest("hex");
@@ -49,6 +85,7 @@ var Vault = class {
49
85
  this.vaultKey = null;
50
86
  this.apiKeyHash = null;
51
87
  this.spSessionCookie = null;
88
+ this.unsealedBy = null;
52
89
  }
53
90
  /**
54
91
  * Check if the vault was created by a different API key.
@@ -522,7 +559,7 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2) {
522
559
  const setCookieHeaders = spRes.headers.getSetCookie?.() ?? [];
523
560
  const sessionCookie = setCookieHeaders.join("; ");
524
561
  vault2.setSpCookie(sessionCookie);
525
- vault2.deriveAndSetKey(apiKey);
562
+ await vault2.deriveAndSetKey(apiKey);
526
563
  if (vault2.isVaultFromDifferentKey()) {
527
564
  if (!confirmWipe) {
528
565
  const credentialIds = vault2.listCredentials();
@@ -546,7 +583,7 @@ function createAuthRouter(vault2, logoutAuth, loginRateLimit2) {
546
583
  console.error("[Control Plane] Failed to remove integrations:", err);
547
584
  }
548
585
  vault2.wipe();
549
- vault2.deriveAndSetKey(apiKey);
586
+ await vault2.deriveAndSetKey(apiKey);
550
587
  }
551
588
  if (sessionCookie) {
552
589
  try {
@@ -657,7 +694,13 @@ function createVaultRouter(vault2) {
657
694
  });
658
695
  router.put("/credentials/:name", async (req, res) => {
659
696
  const { name } = req.params;
660
- const fields = req.body;
697
+ const incoming = req.body;
698
+ let fields = incoming;
699
+ try {
700
+ const existing = vault2.getCredential(name);
701
+ if (existing) fields = { ...existing, ...incoming };
702
+ } catch {
703
+ }
661
704
  vault2.setCredential(name, fields);
662
705
  try {
663
706
  await pushServiceCredentials(name, fields);
@@ -1061,6 +1104,38 @@ async function getIntentReview(config, request) {
1061
1104
  };
1062
1105
  }
1063
1106
  }
1107
+ async function listAIModels(config) {
1108
+ try {
1109
+ if (config.provider === "ollama") {
1110
+ const res2 = await fetch(`${config.endpoint}/api/tags`, {
1111
+ signal: AbortSignal.timeout(5e3)
1112
+ });
1113
+ if (!res2.ok) throw new Error(`Ollama: ${res2.status}`);
1114
+ const data = await res2.json();
1115
+ const models2 = (data.models ?? []).map((m) => m.name).filter((n) => !!n).sort();
1116
+ return { ok: true, models: models2 };
1117
+ }
1118
+ const headers = {};
1119
+ if (config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
1120
+ const res = await fetch(`${config.endpoint}/models`, {
1121
+ headers,
1122
+ signal: AbortSignal.timeout(8e3)
1123
+ });
1124
+ if (!res.ok) {
1125
+ if (res.status === 401 || res.status === 403) {
1126
+ throw new Error("Enter this provider\u2019s API key, then Refresh");
1127
+ }
1128
+ const text = await res.text().catch(() => "");
1129
+ throw new Error(`AI provider: ${res.status}${text ? ` - ${text}` : ""}`);
1130
+ }
1131
+ const raw = await res.json();
1132
+ const list = Array.isArray(raw) ? raw : raw.data ?? [];
1133
+ const models = list.map((m) => m.id).filter((n) => !!n).sort();
1134
+ return { ok: true, models };
1135
+ } catch (err) {
1136
+ return { ok: false, models: [], message: err instanceof Error ? err.message : "Failed to list models" };
1137
+ }
1138
+ }
1064
1139
  async function testAIConnectivity(config) {
1065
1140
  try {
1066
1141
  if (config.provider === "ollama") {
@@ -1175,16 +1250,19 @@ function createAIRouter(vault2) {
1175
1250
  });
1176
1251
  router.post("/test", async (req, res) => {
1177
1252
  const body = req.body;
1253
+ const stored = loadAIConfig();
1178
1254
  let config;
1179
1255
  if (body?.endpoint) {
1180
1256
  config = {
1181
- provider: body.provider || "ollama",
1257
+ provider: body.provider || "openai-compatible",
1182
1258
  endpoint: body.endpoint,
1183
1259
  model: body.model || "",
1184
- apiKey: body.apiKey
1260
+ // Fall back to the stored key only when it belongs to the SAME
1261
+ // endpoint — so testing a different provider without its key fails
1262
+ // honestly instead of passing on an unrelated stored key.
1263
+ apiKey: body.apiKey || (stored && stored.endpoint === body.endpoint ? stored.apiKey : void 0)
1185
1264
  };
1186
1265
  } else {
1187
- const stored = loadAIConfig();
1188
1266
  if (!stored) {
1189
1267
  res.status(400).json({ ok: false, message: "No AI config stored" });
1190
1268
  return;
@@ -1194,6 +1272,27 @@ function createAIRouter(vault2) {
1194
1272
  const result = await testAIConnectivity(config);
1195
1273
  res.json(result);
1196
1274
  });
1275
+ router.post("/models", async (req, res) => {
1276
+ const body = req.body;
1277
+ const stored = loadAIConfig();
1278
+ let config;
1279
+ if (body?.endpoint) {
1280
+ config = {
1281
+ provider: body.provider || "openai-compatible",
1282
+ endpoint: body.endpoint,
1283
+ model: body.model || "",
1284
+ apiKey: body.apiKey || (stored && stored.endpoint === body.endpoint ? stored.apiKey : void 0)
1285
+ };
1286
+ } else {
1287
+ config = stored;
1288
+ }
1289
+ if (!config) {
1290
+ res.status(400).json({ ok: false, models: [], message: "AI not configured. Pick a provider first." });
1291
+ return;
1292
+ }
1293
+ const result = await listAIModels(config);
1294
+ res.json(result);
1295
+ });
1197
1296
  router.get("/presets", (_req, res) => {
1198
1297
  res.json({ presets: PROVIDER_PRESETS });
1199
1298
  });
@@ -1362,11 +1461,161 @@ function createMCPRouter() {
1362
1461
  return router;
1363
1462
  }
1364
1463
 
1365
- // src/routes/encrypt-intent.ts
1464
+ // src/routes/autostart.ts
1366
1465
  import { Router as Router6 } from "express";
1466
+ import { execFile } from "child_process";
1467
+ import { existsSync as existsSync2 } from "fs";
1468
+ import { dirname as pathDirname, resolve } from "path";
1469
+ import { fileURLToPath } from "url";
1470
+ import { promisify } from "util";
1471
+ var run = promisify(execFile);
1472
+ var SUPPORTED = /* @__PURE__ */ new Set(["darwin", "win32", "linux"]);
1473
+ var MODULE_DIR = pathDirname(fileURLToPath(import.meta.url));
1474
+ function findCli(dirname3 = MODULE_DIR) {
1475
+ const candidates = [
1476
+ // Bundled (the shipped layout): dist/control-plane → dist → root → bin
1477
+ resolve(dirname3, "..", "..", "bin", "suveren-gateway.js"),
1478
+ // Bundled, were the routes/ directory ever preserved.
1479
+ resolve(dirname3, "..", "..", "..", "bin", "suveren-gateway.js"),
1480
+ // Dev, running from source: the repo's own bundle directory.
1481
+ resolve(dirname3, "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js"),
1482
+ resolve(dirname3, "..", "..", "..", "..", "..", "bundle", "bin", "suveren-gateway.js")
1483
+ // Deliberately NO process.cwd() fallback: it makes the result depend on
1484
+ // where the process happened to be launched from, so the same install
1485
+ // resolves differently between a shell and a login service — and it would
1486
+ // mask a genuinely missing CLI whenever the cwd happened to be the repo.
1487
+ ];
1488
+ return candidates.find(existsSync2) ?? null;
1489
+ }
1490
+ async function cli(args) {
1491
+ const bin = findCli();
1492
+ if (!bin) return { ok: false, output: "CLI not found" };
1493
+ try {
1494
+ const { stdout, stderr } = await run(process.execPath, [bin, ...args], {
1495
+ timeout: 6e4,
1496
+ env: process.env
1497
+ });
1498
+ return { ok: true, output: `${stdout}${stderr}`.trim() };
1499
+ } catch (err) {
1500
+ const e = err;
1501
+ return { ok: false, output: `${e.stdout ?? ""}${e.stderr ?? ""}`.trim() || e.message || "failed" };
1502
+ }
1503
+ }
1504
+ function safe(handler) {
1505
+ return (req, res) => {
1506
+ handler(req, res).catch((err) => {
1507
+ const message = err instanceof Error ? err.message : String(err);
1508
+ console.error("[Autostart] handler failed:", message);
1509
+ if (!res.headersSent) res.status(500).json({ error: "autostart_failed", message });
1510
+ });
1511
+ };
1512
+ }
1513
+ function createAutostartRouter() {
1514
+ const router = Router6();
1515
+ router.get("/", safe(async (_req, res) => {
1516
+ const platform = process.platform;
1517
+ const supported = SUPPORTED.has(platform);
1518
+ const bin = findCli();
1519
+ if (!supported || !bin) {
1520
+ res.json({
1521
+ supported: false,
1522
+ installed: false,
1523
+ platform,
1524
+ // Be specific about WHICH of the two reasons applies — "unavailable"
1525
+ // with no cause is the kind of dead end that generates support mail.
1526
+ reason: !supported ? `Autostart is not available on ${platform}.` : "Autostart needs the packaged gateway; it is unavailable when running from source."
1527
+ });
1528
+ return;
1529
+ }
1530
+ const { output } = await cli(["service", "status"]);
1531
+ res.json({
1532
+ supported: true,
1533
+ installed: /Login service:\s*installed/i.test(output),
1534
+ platform,
1535
+ detail: output
1536
+ });
1537
+ }));
1538
+ router.post("/", safe(async (_req, res) => {
1539
+ if (!SUPPORTED.has(process.platform) || !findCli()) {
1540
+ res.status(400).json({ error: "unsupported", message: "Autostart is not available here." });
1541
+ return;
1542
+ }
1543
+ const { ok, output } = await cli(["service", "install"]);
1544
+ if (!ok) {
1545
+ res.status(500).json({ error: "install_failed", message: output });
1546
+ return;
1547
+ }
1548
+ res.json({ ok: true, installed: true, detail: output });
1549
+ }));
1550
+ router.delete("/", safe(async (_req, res) => {
1551
+ if (!SUPPORTED.has(process.platform) || !findCli()) {
1552
+ res.status(400).json({ error: "unsupported", message: "Autostart is not available here." });
1553
+ return;
1554
+ }
1555
+ const { ok, output } = await cli(["service", "uninstall"]);
1556
+ if (!ok) {
1557
+ res.status(500).json({ error: "uninstall_failed", message: output });
1558
+ return;
1559
+ }
1560
+ res.json({ ok: true, installed: false, detail: output });
1561
+ }));
1562
+ return router;
1563
+ }
1564
+
1565
+ // src/lib/desktop-notify.ts
1566
+ import { spawn } from "child_process";
1567
+ function osaQuote(value) {
1568
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
1569
+ }
1570
+ function psQuote(value) {
1571
+ return `'${value.replace(/'/g, "''")}'`;
1572
+ }
1573
+ function buildNotifyCommand(platform, title, message) {
1574
+ switch (platform) {
1575
+ case "darwin":
1576
+ return {
1577
+ cmd: "osascript",
1578
+ args: ["-e", `display notification ${osaQuote(message)} with title ${osaQuote(title)}`]
1579
+ };
1580
+ case "win32":
1581
+ return {
1582
+ cmd: "powershell",
1583
+ args: [
1584
+ "-NoProfile",
1585
+ "-NonInteractive",
1586
+ "-Command",
1587
+ `Add-Type -AssemblyName System.Windows.Forms; $n = New-Object System.Windows.Forms.NotifyIcon; $n.Icon = [System.Drawing.SystemIcons]::Information; $n.BalloonTipTitle = ${psQuote(title)}; $n.BalloonTipText = ${psQuote(message)}; $n.Visible = $true; $n.ShowBalloonTip(15000); Start-Sleep -Seconds 16; $n.Dispose()`
1588
+ ]
1589
+ };
1590
+ case "linux":
1591
+ return { cmd: "notify-send", args: ["--app-name=Suveren", title, message] };
1592
+ default:
1593
+ return null;
1594
+ }
1595
+ }
1596
+ function lockedNotification(port2) {
1597
+ return {
1598
+ title: "Suveren is running but locked",
1599
+ message: `Your agent has no authority until you unlock it. Open http://localhost:${port2} and enter your API key.`
1600
+ };
1601
+ }
1602
+ function notify(title, message, platform = process.platform) {
1603
+ const command = buildNotifyCommand(platform, title, message);
1604
+ if (!command) return;
1605
+ try {
1606
+ const child = spawn(command.cmd, command.args, { detached: true, stdio: "ignore" });
1607
+ child.on("error", () => {
1608
+ });
1609
+ child.unref();
1610
+ } catch {
1611
+ }
1612
+ }
1613
+
1614
+ // src/routes/encrypt-intent.ts
1615
+ import { Router as Router7 } from "express";
1367
1616
  import { computeIntentDisclosureHash } from "@hap/core";
1368
1617
  function createEncryptIntentRouter() {
1369
- const router = Router6();
1618
+ const router = Router7();
1370
1619
  router.post("/", async (req, res) => {
1371
1620
  const { intent, recipients } = req.body;
1372
1621
  if (typeof intent !== "string" || intent.length === 0) {
@@ -1428,9 +1677,9 @@ function createEncryptIntentRouter() {
1428
1677
  }
1429
1678
 
1430
1679
  // src/routes/decrypt-intent.ts
1431
- import { Router as Router7 } from "express";
1680
+ import { Router as Router8 } from "express";
1432
1681
  function createDecryptIntentRouter(vault2) {
1433
- const router = Router7();
1682
+ const router = Router8();
1434
1683
  router.post("/", async (req, res) => {
1435
1684
  const { intentCiphertext, encryptedKey, approverId } = req.body;
1436
1685
  if (typeof intentCiphertext !== "string" || intentCiphertext.length === 0) {
@@ -1469,14 +1718,14 @@ function createDecryptIntentRouter(vault2) {
1469
1718
  }
1470
1719
 
1471
1720
  // src/routes/approved-intents.ts
1472
- import { Router as Router8 } from "express";
1473
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
1721
+ import { Router as Router9 } from "express";
1722
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
1474
1723
  import { homedir as homedir2 } from "os";
1475
1724
  import { join as join2 } from "path";
1476
1725
  var SUVEREN_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join2(homedir2(), ".suveren");
1477
1726
  var FILE_PATH = join2(SUVEREN_DATA_DIR, "approved-intents.enc.json");
1478
1727
  function readFile() {
1479
- if (!existsSync2(FILE_PATH)) {
1728
+ if (!existsSync3(FILE_PATH)) {
1480
1729
  return { version: 1, entries: {} };
1481
1730
  }
1482
1731
  try {
@@ -1490,7 +1739,7 @@ function writeFile(data) {
1490
1739
  writeFileSync2(FILE_PATH, JSON.stringify(data, null, 2), "utf-8");
1491
1740
  }
1492
1741
  function createApprovedIntentsRouter(vault2) {
1493
- const router = Router8();
1742
+ const router = Router9();
1494
1743
  router.get("/", (req, res) => {
1495
1744
  try {
1496
1745
  const file = readFile();
@@ -1534,7 +1783,7 @@ function createApprovedIntentsRouter(vault2) {
1534
1783
  // src/lib/update-checker.ts
1535
1784
  import { execSync } from "child_process";
1536
1785
  import { dirname as dirname2 } from "path";
1537
- import { fileURLToPath } from "url";
1786
+ import { fileURLToPath as fileURLToPath2 } from "url";
1538
1787
  var GHCR_IMAGE = "suverenai/suveren-gateway";
1539
1788
  var NPM_PACKAGE = "@suveren/gateway";
1540
1789
  var CHECK_INTERVAL = 60 * 60 * 1e3;
@@ -1599,7 +1848,7 @@ function compareSemver(a, b) {
1599
1848
  return 0;
1600
1849
  }
1601
1850
  function checkDev() {
1602
- const cwd = dirname2(fileURLToPath(import.meta.url));
1851
+ const cwd = dirname2(fileURLToPath2(import.meta.url));
1603
1852
  try {
1604
1853
  execSync("git fetch origin --quiet", { cwd, stdio: "ignore", timeout: 15e3 });
1605
1854
  const out = execSync("git rev-list HEAD..origin/main --count", {
@@ -1667,12 +1916,35 @@ data: ${data}
1667
1916
  };
1668
1917
  }
1669
1918
 
1919
+ // src/lib/denials-reader.ts
1920
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1921
+ import { join as join3 } from "path";
1922
+ function loadDenials(dataDir, decrypt) {
1923
+ const encPath = join3(dataDir, "denials.enc.json");
1924
+ const plainPath = join3(dataDir, "denials.json");
1925
+ if (existsSync4(encPath)) {
1926
+ const { blob } = JSON.parse(readFileSync3(encPath, "utf-8"));
1927
+ return JSON.parse(decrypt(blob)).records ?? [];
1928
+ }
1929
+ if (existsSync4(plainPath)) {
1930
+ return JSON.parse(readFileSync3(plainPath, "utf-8")).records ?? [];
1931
+ }
1932
+ return [];
1933
+ }
1934
+ function selectDenials(records, opts = {}) {
1935
+ let out = [...records].sort((a, b) => b.ts - a.ts);
1936
+ if (opts.since !== void 0 && Number.isFinite(opts.since)) out = out.filter((r) => r.ts >= opts.since);
1937
+ const count = out.length;
1938
+ if (opts.limit !== void 0 && Number.isFinite(opts.limit) && opts.limit > 0) out = out.slice(0, opts.limit);
1939
+ return { count, records: out };
1940
+ }
1941
+
1670
1942
  // src/index.ts
1671
1943
  (function migrateDataDir() {
1672
1944
  if (process.env.SUVEREN_DATA_DIR) return;
1673
- const oldDir = join3(homedir3(), ".hap");
1674
- const newDir = join3(homedir3(), ".suveren");
1675
- if (!existsSync3(newDir) && existsSync3(oldDir)) {
1945
+ const oldDir = join4(homedir3(), ".hap");
1946
+ const newDir = join4(homedir3(), ".suveren");
1947
+ if (!existsSync5(newDir) && existsSync5(oldDir)) {
1676
1948
  try {
1677
1949
  renameSync(oldDir, newDir);
1678
1950
  console.error(`[Control Plane] Migrated data directory: ${oldDir} \u2192 ${newDir}`);
@@ -1685,7 +1957,7 @@ data: ${data}
1685
1957
  var SP_URL2 = process.env.SUVEREN_AS_URL ?? "https://www.suveren.ai";
1686
1958
  var port = parseInt(process.env.SUVEREN_CP_PORT ?? "3402", 10);
1687
1959
  var HAP_MODE = process.env.HAP_MODE ?? "personal";
1688
- var UI_DIST = process.env.HAP_UI_DIST ?? join3(import.meta.dirname ?? __dirname, "../../ui/dist");
1960
+ var UI_DIST = process.env.HAP_UI_DIST ?? join4(import.meta.dirname ?? __dirname, "../../ui/dist");
1689
1961
  var vault = new Vault();
1690
1962
  var internalSecret2 = process.env.SUVEREN_INTERNAL_SECRET ?? randomBytes2(32).toString("hex");
1691
1963
  setInternalSecret(internalSecret2);
@@ -1919,6 +2191,7 @@ app.use("/vault", jsonParser, authGuard, createVaultRouter(vault));
1919
2191
  app.use("/ai", jsonParser, authGuard, createAIRouter(vault));
1920
2192
  app.use("/ai-prompts", jsonParser, authGuard, createAIPromptsRouter());
1921
2193
  app.use("/mcp", jsonParser, authGuard, createMCPRouter());
2194
+ app.use("/autostart", jsonParser, authGuard, createAutostartRouter());
1922
2195
  app.use("/api/encrypt-intent", jsonParser, authGuard, createEncryptIntentRouter());
1923
2196
  app.use("/api/decrypt-intent", jsonParser, authGuard, createDecryptIntentRouter(vault));
1924
2197
  app.use("/api/approved-intents", jsonParser, authGuard, createApprovedIntentsRouter(vault));
@@ -2033,6 +2306,21 @@ app.get("/active-authorizations", authGuard, async (_req, res) => {
2033
2306
  res.status(500).json({ error: "Failed to fetch authorizations from MCP server" });
2034
2307
  }
2035
2308
  });
2309
+ app.get("/denials", authGuard, (req, res) => {
2310
+ try {
2311
+ const dataDir = process.env.SUVEREN_DATA_DIR ?? join4(homedir3(), ".suveren");
2312
+ const all = loadDenials(dataDir, (blob) => vault.decrypt(blob));
2313
+ const since = Number(req.query.since);
2314
+ const limit = Number(req.query.limit);
2315
+ res.json(selectDenials(all, {
2316
+ since: Number.isFinite(since) ? since : void 0,
2317
+ limit: Number.isFinite(limit) ? limit : void 0
2318
+ }));
2319
+ } catch (err) {
2320
+ console.error("[Control Plane] Denial log read error:", err);
2321
+ res.status(500).json({ error: "Could not read the denial log" });
2322
+ }
2323
+ });
2036
2324
  app.post("/gate-content", jsonParser, authGuard, async (req, res) => {
2037
2325
  try {
2038
2326
  const { authorizationId, boundsHash, contextHash, context, contextLabels, path, gateContent } = req.body;
@@ -2053,16 +2341,16 @@ app.post("/resync-gates", authGuard, async (_req, res) => {
2053
2341
  }
2054
2342
  });
2055
2343
  var AGENT_CONTEXT_MAX_BYTES = 16 * 1024;
2056
- var SUVEREN_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join3(homedir3(), ".suveren");
2344
+ var SUVEREN_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join4(homedir3(), ".suveren");
2057
2345
  app.get("/agent-brief/context", authGuard, async (_req, res) => {
2058
2346
  try {
2059
- const { readFileSync: readFileSync4, existsSync: fileExists } = await import("fs");
2060
- const filePath = join3(SUVEREN_DATA_DIR2, "context.md");
2347
+ const { readFileSync: readFileSync5, existsSync: fileExists } = await import("fs");
2348
+ const filePath = join4(SUVEREN_DATA_DIR2, "context.md");
2061
2349
  if (!fileExists(filePath)) {
2062
2350
  res.json({ content: "" });
2063
2351
  return;
2064
2352
  }
2065
- const content = readFileSync4(filePath, "utf-8");
2353
+ const content = readFileSync5(filePath, "utf-8");
2066
2354
  res.json({ content });
2067
2355
  } catch (err) {
2068
2356
  console.error("[Control Plane] agent-brief/context GET failed:", err);
@@ -2082,7 +2370,7 @@ app.put("/agent-brief/context", jsonParser, authGuard, async (req, res) => {
2082
2370
  }
2083
2371
  const { mkdirSync: mkdirSync3, writeFileSync: writeFileSync3, renameSync: renameSync2 } = await import("fs");
2084
2372
  mkdirSync3(SUVEREN_DATA_DIR2, { recursive: true });
2085
- const filePath = join3(SUVEREN_DATA_DIR2, "context.md");
2373
+ const filePath = join4(SUVEREN_DATA_DIR2, "context.md");
2086
2374
  const tmpPath = `${filePath}.tmp`;
2087
2375
  writeFileSync3(tmpPath, content, "utf-8");
2088
2376
  renameSync2(tmpPath, filePath);
@@ -2134,7 +2422,7 @@ app.use(
2134
2422
  })
2135
2423
  );
2136
2424
  function detectInstallMethod() {
2137
- if (existsSync3("/.dockerenv")) return "docker";
2425
+ if (existsSync5("/.dockerenv")) return "docker";
2138
2426
  const dir = import.meta.dirname ?? __dirname;
2139
2427
  if (dir.includes("/node_modules/@suveren/gateway/")) return "npm";
2140
2428
  return "dev";
@@ -2145,10 +2433,10 @@ function detectRunningVersion() {
2145
2433
  return process.env.HAP_BUILD_SHA ?? "dev";
2146
2434
  }
2147
2435
  const dir = import.meta.dirname ?? __dirname;
2148
- const bundlePkg = join3(dir, "..", "..", "package.json");
2149
- if (existsSync3(bundlePkg)) {
2436
+ const bundlePkg = join4(dir, "..", "..", "package.json");
2437
+ if (existsSync5(bundlePkg)) {
2150
2438
  try {
2151
- const pkg = JSON.parse(readFileSync3(bundlePkg, "utf8"));
2439
+ const pkg = JSON.parse(readFileSync4(bundlePkg, "utf8"));
2152
2440
  if (pkg.name === "@suveren/gateway" && typeof pkg.version === "string") {
2153
2441
  return pkg.version;
2154
2442
  }
@@ -2176,7 +2464,7 @@ app.get("/health", async (req, res) => {
2176
2464
  }
2177
2465
  });
2178
2466
  });
2179
- if (existsSync3(UI_DIST)) {
2467
+ if (existsSync5(UI_DIST)) {
2180
2468
  app.use(express.static(UI_DIST, {
2181
2469
  setHeaders: (res, filePath) => {
2182
2470
  if (filePath.endsWith("index.html")) {
@@ -2186,7 +2474,7 @@ if (existsSync3(UI_DIST)) {
2186
2474
  }));
2187
2475
  app.get("*", (_req, res) => {
2188
2476
  res.setHeader("Cache-Control", "no-store, must-revalidate");
2189
- res.sendFile(join3(UI_DIST, "index.html"));
2477
+ res.sendFile(join4(UI_DIST, "index.html"));
2190
2478
  });
2191
2479
  } else {
2192
2480
  app.get("/", (_req, res) => {
@@ -2198,6 +2486,10 @@ if (existsSync3(UI_DIST)) {
2198
2486
  }
2199
2487
  app.listen(port, "0.0.0.0", () => {
2200
2488
  console.error(`[Control Plane] Listening on http://0.0.0.0:${port}`);
2489
+ if (process.env.SUVEREN_AUTOSTART === "1" && !vault.isUnlocked()) {
2490
+ const { title, message } = lockedNotification(port);
2491
+ notify(title, message);
2492
+ }
2201
2493
  console.error(`[Control Plane] SP proxy: ${SP_URL2}`);
2202
2494
  console.error(`[Control Plane] UI dist: ${UI_DIST}`);
2203
2495
  console.error(`[Control Plane] Internal secret: configured`);