@maudecode/talaria-web 0.0.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 (876) hide show
  1. package/contract_versions.json +18 -0
  2. package/dist/api/auth-raw.d.ts +9 -0
  3. package/dist/api/auth-raw.js +134 -0
  4. package/dist/api/auth-raw.js.map +1 -0
  5. package/dist/api/automation-raw.d.ts +16 -0
  6. package/dist/api/automation-raw.js +340 -0
  7. package/dist/api/automation-raw.js.map +1 -0
  8. package/dist/api/automation-router.d.ts +788 -0
  9. package/dist/api/automation-router.js +248 -0
  10. package/dist/api/automation-router.js.map +1 -0
  11. package/dist/api/chat-router.d.ts +375 -0
  12. package/dist/api/chat-router.js +446 -0
  13. package/dist/api/chat-router.js.map +1 -0
  14. package/dist/api/git-router.d.ts +681 -0
  15. package/dist/api/git-router.js +275 -0
  16. package/dist/api/git-router.js.map +1 -0
  17. package/dist/api/raw-routes.d.ts +10 -0
  18. package/dist/api/raw-routes.js +466 -0
  19. package/dist/api/raw-routes.js.map +1 -0
  20. package/dist/api/router.d.ts +226 -0
  21. package/dist/api/router.js +331 -0
  22. package/dist/api/router.js.map +1 -0
  23. package/dist/api/session-visibility.d.ts +12 -0
  24. package/dist/api/session-visibility.js +51 -0
  25. package/dist/api/session-visibility.js.map +1 -0
  26. package/dist/api/sessions-router.d.ts +1728 -0
  27. package/dist/api/sessions-router.js +815 -0
  28. package/dist/api/sessions-router.js.map +1 -0
  29. package/dist/api/settings-router.d.ts +592 -0
  30. package/dist/api/settings-router.js +474 -0
  31. package/dist/api/settings-router.js.map +1 -0
  32. package/dist/api/sse-routes.d.ts +51 -0
  33. package/dist/api/sse-routes.js +602 -0
  34. package/dist/api/sse-routes.js.map +1 -0
  35. package/dist/api/tools-raw.d.ts +5 -0
  36. package/dist/api/tools-raw.js +291 -0
  37. package/dist/api/tools-raw.js.map +1 -0
  38. package/dist/api/tools-router.d.ts +494 -0
  39. package/dist/api/tools-router.js +349 -0
  40. package/dist/api/tools-router.js.map +1 -0
  41. package/dist/app.d.ts +4787 -0
  42. package/dist/app.js +453 -0
  43. package/dist/app.js.map +1 -0
  44. package/dist/auth/cookies.d.ts +17 -0
  45. package/dist/auth/cookies.js +42 -0
  46. package/dist/auth/cookies.js.map +1 -0
  47. package/dist/auth/crypto.d.ts +9 -0
  48. package/dist/auth/crypto.js +38 -0
  49. package/dist/auth/crypto.js.map +1 -0
  50. package/dist/auth/gate.d.ts +39 -0
  51. package/dist/auth/gate.js +406 -0
  52. package/dist/auth/gate.js.map +1 -0
  53. package/dist/auth/oidc.d.ts +138 -0
  54. package/dist/auth/oidc.js +836 -0
  55. package/dist/auth/oidc.js.map +1 -0
  56. package/dist/auth/passkeys.d.ts +49 -0
  57. package/dist/auth/passkeys.js +310 -0
  58. package/dist/auth/passkeys.js.map +1 -0
  59. package/dist/auth/store.d.ts +116 -0
  60. package/dist/auth/store.js +485 -0
  61. package/dist/auth/store.js.map +1 -0
  62. package/dist/bin/talaria-web-mcp.d.ts +2 -0
  63. package/dist/bin/talaria-web-mcp.js +12 -0
  64. package/dist/bin/talaria-web-mcp.js.map +1 -0
  65. package/dist/bin/talaria-web.d.ts +2 -0
  66. package/dist/bin/talaria-web.js +87 -0
  67. package/dist/bin/talaria-web.js.map +1 -0
  68. package/dist/cli/ctl.d.ts +58 -0
  69. package/dist/cli/ctl.js +643 -0
  70. package/dist/cli/ctl.js.map +1 -0
  71. package/dist/cli/dotenv.d.ts +30 -0
  72. package/dist/cli/dotenv.js +115 -0
  73. package/dist/cli/dotenv.js.map +1 -0
  74. package/dist/cli/launcher.d.ts +49 -0
  75. package/dist/cli/launcher.js +213 -0
  76. package/dist/cli/launcher.js.map +1 -0
  77. package/dist/cli/supervise.d.ts +10 -0
  78. package/dist/cli/supervise.js +33 -0
  79. package/dist/cli/supervise.js.map +1 -0
  80. package/dist/cli/web-root.d.ts +2 -0
  81. package/dist/cli/web-root.js +23 -0
  82. package/dist/cli/web-root.js.map +1 -0
  83. package/dist/config/agent-config.d.ts +109 -0
  84. package/dist/config/agent-config.js +632 -0
  85. package/dist/config/agent-config.js.map +1 -0
  86. package/dist/config.d.ts +36 -0
  87. package/dist/config.js +105 -0
  88. package/dist/config.js.map +1 -0
  89. package/dist/fs/atomic.d.ts +7 -0
  90. package/dist/fs/atomic.js +68 -0
  91. package/dist/fs/atomic.js.map +1 -0
  92. package/dist/http/addresses.d.ts +5 -0
  93. package/dist/http/addresses.js +68 -0
  94. package/dist/http/addresses.js.map +1 -0
  95. package/dist/http/capped.d.ts +2 -0
  96. package/dist/http/capped.js +22 -0
  97. package/dist/http/capped.js.map +1 -0
  98. package/dist/http/context.d.ts +281 -0
  99. package/dist/http/context.js +327 -0
  100. package/dist/http/context.js.map +1 -0
  101. package/dist/http/csp.d.ts +11 -0
  102. package/dist/http/csp.js +51 -0
  103. package/dist/http/csp.js.map +1 -0
  104. package/dist/http/origin.d.ts +39 -0
  105. package/dist/http/origin.js +183 -0
  106. package/dist/http/origin.js.map +1 -0
  107. package/dist/http/pinned.d.ts +18 -0
  108. package/dist/http/pinned.js +62 -0
  109. package/dist/http/pinned.js.map +1 -0
  110. package/dist/index.d.ts +10 -0
  111. package/dist/index.js +12 -0
  112. package/dist/index.js.map +1 -0
  113. package/dist/mcp/server.d.ts +29 -0
  114. package/dist/mcp/server.js +221 -0
  115. package/dist/mcp/server.js.map +1 -0
  116. package/dist/onboarding.d.ts +57 -0
  117. package/dist/onboarding.js +381 -0
  118. package/dist/onboarding.js.map +1 -0
  119. package/dist/profiles/profiles.d.ts +96 -0
  120. package/dist/profiles/profiles.js +476 -0
  121. package/dist/profiles/profiles.js.map +1 -0
  122. package/dist/projects.d.ts +36 -0
  123. package/dist/projects.js +102 -0
  124. package/dist/projects.js.map +1 -0
  125. package/dist/providers/catalog.d.ts +118 -0
  126. package/dist/providers/catalog.js +868 -0
  127. package/dist/providers/catalog.js.map +1 -0
  128. package/dist/providers/env-file.d.ts +6 -0
  129. package/dist/providers/env-file.js +106 -0
  130. package/dist/providers/env-file.js.map +1 -0
  131. package/dist/providers/runtime-env.d.ts +20 -0
  132. package/dist/providers/runtime-env.js +85 -0
  133. package/dist/providers/runtime-env.js.map +1 -0
  134. package/dist/providers/tables.d.ts +54 -0
  135. package/dist/providers/tables.js +54 -0
  136. package/dist/providers/tables.js.map +1 -0
  137. package/dist/redact.d.ts +23 -0
  138. package/dist/redact.js +337 -0
  139. package/dist/redact.js.map +1 -0
  140. package/dist/release.d.ts +16 -0
  141. package/dist/release.js +114 -0
  142. package/dist/release.js.map +1 -0
  143. package/dist/runtime.d.ts +21 -0
  144. package/dist/runtime.js +680 -0
  145. package/dist/runtime.js.map +1 -0
  146. package/dist/server.d.ts +20 -0
  147. package/dist/server.js +90 -0
  148. package/dist/server.js.map +1 -0
  149. package/dist/sessions/anchor.d.ts +43 -0
  150. package/dist/sessions/anchor.js +311 -0
  151. package/dist/sessions/anchor.js.map +1 -0
  152. package/dist/sessions/cli-sessions.d.ts +27 -0
  153. package/dist/sessions/cli-sessions.js +158 -0
  154. package/dist/sessions/cli-sessions.js.map +1 -0
  155. package/dist/sessions/completions.d.ts +62 -0
  156. package/dist/sessions/completions.js +332 -0
  157. package/dist/sessions/completions.js.map +1 -0
  158. package/dist/sessions/drafts.d.ts +26 -0
  159. package/dist/sessions/drafts.js +117 -0
  160. package/dist/sessions/drafts.js.map +1 -0
  161. package/dist/sessions/events.d.ts +32 -0
  162. package/dist/sessions/events.js +80 -0
  163. package/dist/sessions/events.js.map +1 -0
  164. package/dist/sessions/export.d.ts +4 -0
  165. package/dist/sessions/export.js +186 -0
  166. package/dist/sessions/export.js.map +1 -0
  167. package/dist/sessions/gateway-watcher.d.ts +58 -0
  168. package/dist/sessions/gateway-watcher.js +199 -0
  169. package/dist/sessions/gateway-watcher.js.map +1 -0
  170. package/dist/sessions/journal.d.ts +103 -0
  171. package/dist/sessions/journal.js +543 -0
  172. package/dist/sessions/journal.js.map +1 -0
  173. package/dist/sessions/list.d.ts +130 -0
  174. package/dist/sessions/list.js +846 -0
  175. package/dist/sessions/list.js.map +1 -0
  176. package/dist/sessions/merge.d.ts +57 -0
  177. package/dist/sessions/merge.js +517 -0
  178. package/dist/sessions/merge.js.map +1 -0
  179. package/dist/sessions/pending.d.ts +69 -0
  180. package/dist/sessions/pending.js +271 -0
  181. package/dist/sessions/pending.js.map +1 -0
  182. package/dist/sessions/reasoning-titles.d.ts +31 -0
  183. package/dist/sessions/reasoning-titles.js +143 -0
  184. package/dist/sessions/reasoning-titles.js.map +1 -0
  185. package/dist/sessions/relay.d.ts +131 -0
  186. package/dist/sessions/relay.js +577 -0
  187. package/dist/sessions/relay.js.map +1 -0
  188. package/dist/sessions/service.d.ts +189 -0
  189. package/dist/sessions/service.js +1344 -0
  190. package/dist/sessions/service.js.map +1 -0
  191. package/dist/sessions/session.d.ts +131 -0
  192. package/dist/sessions/session.js +505 -0
  193. package/dist/sessions/session.js.map +1 -0
  194. package/dist/sessions/shares.d.ts +31 -0
  195. package/dist/sessions/shares.js +267 -0
  196. package/dist/sessions/shares.js.map +1 -0
  197. package/dist/sessions/state-db.d.ts +52 -0
  198. package/dist/sessions/state-db.js +641 -0
  199. package/dist/sessions/state-db.js.map +1 -0
  200. package/dist/sessions/state-saved.d.ts +13 -0
  201. package/dist/sessions/state-saved.js +47 -0
  202. package/dist/sessions/state-saved.js.map +1 -0
  203. package/dist/sessions/store.d.ts +124 -0
  204. package/dist/sessions/store.js +790 -0
  205. package/dist/sessions/store.js.map +1 -0
  206. package/dist/sessions/streams.d.ts +90 -0
  207. package/dist/sessions/streams.js +200 -0
  208. package/dist/sessions/streams.js.map +1 -0
  209. package/dist/sessions/titles.d.ts +17 -0
  210. package/dist/sessions/titles.js +231 -0
  211. package/dist/sessions/titles.js.map +1 -0
  212. package/dist/sessions/todo.d.ts +8 -0
  213. package/dist/sessions/todo.js +72 -0
  214. package/dist/sessions/todo.js.map +1 -0
  215. package/dist/sessions/turn-context.d.ts +27 -0
  216. package/dist/sessions/turn-context.js +136 -0
  217. package/dist/sessions/turn-context.js.map +1 -0
  218. package/dist/sessions/turn.d.ts +178 -0
  219. package/dist/sessions/turn.js +1357 -0
  220. package/dist/sessions/turn.js.map +1 -0
  221. package/dist/sessions/window.d.ts +10 -0
  222. package/dist/sessions/window.js +151 -0
  223. package/dist/sessions/window.js.map +1 -0
  224. package/dist/settings.d.ts +57 -0
  225. package/dist/settings.js +481 -0
  226. package/dist/settings.js.map +1 -0
  227. package/dist/sidecar/client.d.ts +75 -0
  228. package/dist/sidecar/client.js +252 -0
  229. package/dist/sidecar/client.js.map +1 -0
  230. package/dist/sidecar/discover.d.ts +22 -0
  231. package/dist/sidecar/discover.js +146 -0
  232. package/dist/sidecar/discover.js.map +1 -0
  233. package/dist/sidecar/fake.d.ts +37 -0
  234. package/dist/sidecar/fake.js +79 -0
  235. package/dist/sidecar/fake.js.map +1 -0
  236. package/dist/spa.d.ts +42 -0
  237. package/dist/spa.js +145 -0
  238. package/dist/spa.js.map +1 -0
  239. package/dist/startup.d.ts +19 -0
  240. package/dist/startup.js +44 -0
  241. package/dist/startup.js.map +1 -0
  242. package/dist/test/harness.d.ts +41 -0
  243. package/dist/test/harness.js +123 -0
  244. package/dist/test/harness.js.map +1 -0
  245. package/dist/text/diff.d.ts +16 -0
  246. package/dist/text/diff.js +122 -0
  247. package/dist/text/diff.js.map +1 -0
  248. package/dist/text/markdown.d.ts +8 -0
  249. package/dist/text/markdown.js +185 -0
  250. package/dist/text/markdown.js.map +1 -0
  251. package/dist/tools/crons.d.ts +51 -0
  252. package/dist/tools/crons.js +317 -0
  253. package/dist/tools/crons.js.map +1 -0
  254. package/dist/tools/extensions.d.ts +92 -0
  255. package/dist/tools/extensions.js +1096 -0
  256. package/dist/tools/extensions.js.map +1 -0
  257. package/dist/tools/health.d.ts +21 -0
  258. package/dist/tools/health.js +334 -0
  259. package/dist/tools/health.js.map +1 -0
  260. package/dist/tools/hygiene.d.ts +29 -0
  261. package/dist/tools/hygiene.js +112 -0
  262. package/dist/tools/hygiene.js.map +1 -0
  263. package/dist/tools/insights.d.ts +3 -0
  264. package/dist/tools/insights.js +92 -0
  265. package/dist/tools/insights.js.map +1 -0
  266. package/dist/tools/kanban.d.ts +25 -0
  267. package/dist/tools/kanban.js +79 -0
  268. package/dist/tools/kanban.js.map +1 -0
  269. package/dist/tools/mcp-health.d.ts +28 -0
  270. package/dist/tools/mcp-health.js +207 -0
  271. package/dist/tools/mcp-health.js.map +1 -0
  272. package/dist/tools/mcp.d.ts +34 -0
  273. package/dist/tools/mcp.js +269 -0
  274. package/dist/tools/mcp.js.map +1 -0
  275. package/dist/tools/memory.d.ts +20 -0
  276. package/dist/tools/memory.js +216 -0
  277. package/dist/tools/memory.js.map +1 -0
  278. package/dist/tools/skills.d.ts +43 -0
  279. package/dist/tools/skills.js +193 -0
  280. package/dist/tools/skills.js.map +1 -0
  281. package/dist/tools/terminal.d.ts +96 -0
  282. package/dist/tools/terminal.js +324 -0
  283. package/dist/tools/terminal.js.map +1 -0
  284. package/dist/tools/updates.d.ts +151 -0
  285. package/dist/tools/updates.js +1151 -0
  286. package/dist/tools/updates.js.map +1 -0
  287. package/dist/util.d.ts +6 -0
  288. package/dist/util.js +40 -0
  289. package/dist/util.js.map +1 -0
  290. package/dist/workspace/fs.d.ts +61 -0
  291. package/dist/workspace/fs.js +555 -0
  292. package/dist/workspace/fs.js.map +1 -0
  293. package/dist/workspace/git.d.ts +204 -0
  294. package/dist/workspace/git.js +1236 -0
  295. package/dist/workspace/git.js.map +1 -0
  296. package/dist/workspace/media.d.ts +47 -0
  297. package/dist/workspace/media.js +448 -0
  298. package/dist/workspace/media.js.map +1 -0
  299. package/dist/workspace/paths.d.ts +6 -0
  300. package/dist/workspace/paths.js +41 -0
  301. package/dist/workspace/paths.js.map +1 -0
  302. package/dist/workspace/rollback.d.ts +29 -0
  303. package/dist/workspace/rollback.js +337 -0
  304. package/dist/workspace/rollback.js.map +1 -0
  305. package/dist/workspace/unzip.d.ts +9 -0
  306. package/dist/workspace/unzip.js +61 -0
  307. package/dist/workspace/unzip.js.map +1 -0
  308. package/dist/workspace/upload.d.ts +40 -0
  309. package/dist/workspace/upload.js +215 -0
  310. package/dist/workspace/upload.js.map +1 -0
  311. package/dist/workspace/workspaces.d.ts +84 -0
  312. package/dist/workspace/workspaces.js +663 -0
  313. package/dist/workspace/workspaces.js.map +1 -0
  314. package/dist/workspace/worktrees.d.ts +14 -0
  315. package/dist/workspace/worktrees.js +171 -0
  316. package/dist/workspace/worktrees.js.map +1 -0
  317. package/dist/workspace/zip.d.ts +16 -0
  318. package/dist/workspace/zip.js +205 -0
  319. package/dist/workspace/zip.js.map +1 -0
  320. package/package.json +54 -0
  321. package/sidecar/agent_dependency.json +11 -0
  322. package/sidecar/scripts/record-fixtures.py +72 -0
  323. package/sidecar/scripts/replay_sidecar.py +113 -0
  324. package/sidecar/scripts/test.sh +22 -0
  325. package/sidecar/talaria_sidecar/__init__.py +10 -0
  326. package/sidecar/talaria_sidecar/__main__.py +46 -0
  327. package/sidecar/talaria_sidecar/errors.py +41 -0
  328. package/sidecar/talaria_sidecar/home.py +103 -0
  329. package/sidecar/talaria_sidecar/methods/__init__.py +37 -0
  330. package/sidecar/talaria_sidecar/methods/aux.py +160 -0
  331. package/sidecar/talaria_sidecar/methods/chat.py +791 -0
  332. package/sidecar/talaria_sidecar/methods/commands.py +340 -0
  333. package/sidecar/talaria_sidecar/methods/config.py +131 -0
  334. package/sidecar/talaria_sidecar/methods/cron.py +558 -0
  335. package/sidecar/talaria_sidecar/methods/gateway.py +106 -0
  336. package/sidecar/talaria_sidecar/methods/goals.py +225 -0
  337. package/sidecar/talaria_sidecar/methods/kanban.py +723 -0
  338. package/sidecar/talaria_sidecar/methods/mcp.py +65 -0
  339. package/sidecar/talaria_sidecar/methods/process.py +155 -0
  340. package/sidecar/talaria_sidecar/methods/profiles.py +254 -0
  341. package/sidecar/talaria_sidecar/methods/providers.py +241 -0
  342. package/sidecar/talaria_sidecar/methods/runtime.py +68 -0
  343. package/sidecar/talaria_sidecar/methods/skills.py +262 -0
  344. package/sidecar/talaria_sidecar/methods/state_db.py +418 -0
  345. package/sidecar/talaria_sidecar/methods/stt.py +131 -0
  346. package/sidecar/talaria_sidecar/methods/text.py +85 -0
  347. package/sidecar/talaria_sidecar/methods/usage.py +59 -0
  348. package/sidecar/talaria_sidecar/methods/worktree.py +71 -0
  349. package/sidecar/talaria_sidecar/rpc.py +218 -0
  350. package/sidecar/talaria_sidecar/runtime.py +330 -0
  351. package/static/brand/apple-touch-icon.png +0 -0
  352. package/static/brand/brandmark.svg +12 -0
  353. package/static/brand/favicon-192.png +0 -0
  354. package/static/brand/favicon-32.png +0 -0
  355. package/static/brand/favicon-512.png +0 -0
  356. package/static/brand/favicon-512.svg +14 -0
  357. package/static/brand/favicon-dark.svg +14 -0
  358. package/static/brand/favicon-light.svg +14 -0
  359. package/static/brand/favicon.ico +0 -0
  360. package/static/brand/favicon.svg +14 -0
  361. package/static/dist/FILES.txt +515 -0
  362. package/static/dist/assets/AppShell-gs0grlbs.js +1 -0
  363. package/static/dist/assets/ChatPage-gi1xlz52.js +18 -0
  364. package/static/dist/assets/ChatPage-gmu5c7lf.css +1 -0
  365. package/static/dist/assets/HubRoute-qs9vzuh0.js +2 -0
  366. package/static/dist/assets/InterVariable-nonokl6i.woff2 +0 -0
  367. package/static/dist/assets/KaTeX_AMS-Regular-e1why8ff.woff2 +0 -0
  368. package/static/dist/assets/KaTeX_AMS-Regular-mec5w1mt.woff +0 -0
  369. package/static/dist/assets/KaTeX_AMS-Regular-mos1wgtv.ttf +0 -0
  370. package/static/dist/assets/KaTeX_Caligraphic-Bold-axibvb5b.ttf +0 -0
  371. package/static/dist/assets/KaTeX_Caligraphic-Bold-eccvbn5c.woff +0 -0
  372. package/static/dist/assets/KaTeX_Caligraphic-Bold-n63xiolk.woff2 +0 -0
  373. package/static/dist/assets/KaTeX_Caligraphic-Regular-c5dvswgu.ttf +0 -0
  374. package/static/dist/assets/KaTeX_Caligraphic-Regular-iz5gexw5.woff +0 -0
  375. package/static/dist/assets/KaTeX_Caligraphic-Regular-npwmqylf.woff2 +0 -0
  376. package/static/dist/assets/KaTeX_Fraktur-Bold-ftsn4fxp.ttf +0 -0
  377. package/static/dist/assets/KaTeX_Fraktur-Bold-gokmhdpe.woff +0 -0
  378. package/static/dist/assets/KaTeX_Fraktur-Bold-ikhebgtj.woff2 +0 -0
  379. package/static/dist/assets/KaTeX_Fraktur-Regular-hzce8q9o.ttf +0 -0
  380. package/static/dist/assets/KaTeX_Fraktur-Regular-i0egury6.woff2 +0 -0
  381. package/static/dist/assets/KaTeX_Fraktur-Regular-okwm110b.woff +0 -0
  382. package/static/dist/assets/KaTeX_Main-Bold-c5g2m5kh.ttf +0 -0
  383. package/static/dist/assets/KaTeX_Main-Bold-ktk38ybk.woff2 +0 -0
  384. package/static/dist/assets/KaTeX_Main-Bold-ureqgmzo.woff +0 -0
  385. package/static/dist/assets/KaTeX_Main-BoldItalic-bd0upj71.woff +0 -0
  386. package/static/dist/assets/KaTeX_Main-BoldItalic-oj033t4i.woff2 +0 -0
  387. package/static/dist/assets/KaTeX_Main-BoldItalic-opttanob.ttf +0 -0
  388. package/static/dist/assets/KaTeX_Main-Italic-2p4bq1jf.woff2 +0 -0
  389. package/static/dist/assets/KaTeX_Main-Italic-dj86j9xo.ttf +0 -0
  390. package/static/dist/assets/KaTeX_Main-Italic-esmxqs8d.woff +0 -0
  391. package/static/dist/assets/KaTeX_Main-Regular-c978jrkj.ttf +0 -0
  392. package/static/dist/assets/KaTeX_Main-Regular-hbkzldb8.woff2 +0 -0
  393. package/static/dist/assets/KaTeX_Main-Regular-n865mmt0.woff +0 -0
  394. package/static/dist/assets/KaTeX_Math-BoldItalic-cbkxiib1.woff +0 -0
  395. package/static/dist/assets/KaTeX_Math-BoldItalic-hcom2j4y.ttf +0 -0
  396. package/static/dist/assets/KaTeX_Math-BoldItalic-jdo1yxu8.woff2 +0 -0
  397. package/static/dist/assets/KaTeX_Math-Italic-b5lfnctb.ttf +0 -0
  398. package/static/dist/assets/KaTeX_Math-Italic-cz4b2ure.woff2 +0 -0
  399. package/static/dist/assets/KaTeX_Math-Italic-lo894bvj.woff +0 -0
  400. package/static/dist/assets/KaTeX_SansSerif-Bold-h55uj19s.ttf +0 -0
  401. package/static/dist/assets/KaTeX_SansSerif-Bold-m9bkcp3c.woff +0 -0
  402. package/static/dist/assets/KaTeX_SansSerif-Bold-otxc8itm.woff2 +0 -0
  403. package/static/dist/assets/KaTeX_SansSerif-Italic-bp85cocg.ttf +0 -0
  404. package/static/dist/assets/KaTeX_SansSerif-Italic-g42k16nn.woff +0 -0
  405. package/static/dist/assets/KaTeX_SansSerif-Italic-k4kksncm.woff2 +0 -0
  406. package/static/dist/assets/KaTeX_SansSerif-Regular-evq9548m.ttf +0 -0
  407. package/static/dist/assets/KaTeX_SansSerif-Regular-izeggh93.woff +0 -0
  408. package/static/dist/assets/KaTeX_SansSerif-Regular-ltw53ck4.woff2 +0 -0
  409. package/static/dist/assets/KaTeX_Script-Regular-k8v4ghws.ttf +0 -0
  410. package/static/dist/assets/KaTeX_Script-Regular-o2nd302f.woff +0 -0
  411. package/static/dist/assets/KaTeX_Script-Regular-oybd33cp.woff2 +0 -0
  412. package/static/dist/assets/KaTeX_Size1-Regular-cjccv44r.woff2 +0 -0
  413. package/static/dist/assets/KaTeX_Size1-Regular-k13yopgz.woff +0 -0
  414. package/static/dist/assets/KaTeX_Size1-Regular-naiuhmx7.ttf +0 -0
  415. package/static/dist/assets/KaTeX_Size2-Regular-cnnxwlt7.woff +0 -0
  416. package/static/dist/assets/KaTeX_Size2-Regular-hlh6jazj.ttf +0 -0
  417. package/static/dist/assets/KaTeX_Size2-Regular-onxq3bzc.woff2 +0 -0
  418. package/static/dist/assets/KaTeX_Size3-Regular-i00haf83.woff +0 -0
  419. package/static/dist/assets/KaTeX_Size3-Regular-nk2kx36d.ttf +0 -0
  420. package/static/dist/assets/KaTeX_Size4-Regular-effsfy3y.woff +0 -0
  421. package/static/dist/assets/KaTeX_Size4-Regular-myjqyche.ttf +0 -0
  422. package/static/dist/assets/KaTeX_Size4-Regular-nv9nppzf.woff2 +0 -0
  423. package/static/dist/assets/KaTeX_Typewriter-Regular-iqvr3vwu.woff2 +0 -0
  424. package/static/dist/assets/KaTeX_Typewriter-Regular-kzj4h457.woff +0 -0
  425. package/static/dist/assets/KaTeX_Typewriter-Regular-owzsy8p5.ttf +0 -0
  426. package/static/dist/assets/Markdown-bt9bqd6a.js +598 -0
  427. package/static/dist/assets/Markdown-lwviulmg.css +1 -0
  428. package/static/dist/assets/RightPanel-dn19xu42.js +1 -0
  429. package/static/dist/assets/Select-y7wtf85g.js +1 -0
  430. package/static/dist/assets/SessionListPanel-igwdj9xr.js +1 -0
  431. package/static/dist/assets/SettingsLayout-n6mu0ghg.js +1 -0
  432. package/static/dist/assets/States-oil2issf.js +1 -0
  433. package/static/dist/assets/Toaster-jtn59pjm.js +1 -0
  434. package/static/dist/assets/_app-k4jrkgfa.js +1 -0
  435. package/static/dist/assets/_app.ext._extensionId-mmf1mepm.js +1 -0
  436. package/static/dist/assets/_app.index-mb41nf00.js +1 -0
  437. package/static/dist/assets/_app.insights-mz5cep8m.js +1 -0
  438. package/static/dist/assets/_app.kanban-ocgw506i.js +1 -0
  439. package/static/dist/assets/_app.logs-lstmoju6.js +1 -0
  440. package/static/dist/assets/_app.memory-dishj9ra.js +1 -0
  441. package/static/dist/assets/_app.profiles-dynpvsio.js +1 -0
  442. package/static/dist/assets/_app.session._sessionId-kevi4qd2.js +1 -0
  443. package/static/dist/assets/_app.settings-c2czm9v4.js +1 -0
  444. package/static/dist/assets/_app.settings._section-exwflld7.js +1 -0
  445. package/static/dist/assets/_app.skills-j5jh2nug.js +1 -0
  446. package/static/dist/assets/_app.tasks-b99d98fo.js +2 -0
  447. package/static/dist/assets/_app.todos-ma8urvn3.js +1 -0
  448. package/static/dist/assets/_app.workspaces-l86cxeod.js +1 -0
  449. package/static/dist/assets/abap-ij37pki6.js +1 -0
  450. package/static/dist/assets/abnfDiagram-VCTEODGH-hvrr25lb.js +1 -0
  451. package/static/dist/assets/actionscript-3-dz7y3j1x.js +1 -0
  452. package/static/dist/assets/ada-k9zgv987.js +1 -0
  453. package/static/dist/assets/andromeeda-c2n0n86o.js +1 -0
  454. package/static/dist/assets/angular-html-nu6l31w3.js +1 -0
  455. package/static/dist/assets/angular-ts-fbx4f8mm.js +1 -0
  456. package/static/dist/assets/apache-binppq6z.js +1 -0
  457. package/static/dist/assets/apex-h8illjly.js +1 -0
  458. package/static/dist/assets/apl-bx2xr7dh.js +1 -0
  459. package/static/dist/assets/applescript-h0ok5sww.js +1 -0
  460. package/static/dist/assets/ara-dlpjioua.js +1 -0
  461. package/static/dist/assets/arc-7popfhbk.js +1 -0
  462. package/static/dist/assets/architecture-7GRP2DOG-mqft9w2p.js +1 -0
  463. package/static/dist/assets/architectureDiagram-5GKGNRK7-b3r0z8sq.js +36 -0
  464. package/static/dist/assets/array-f36850hm.js +1 -0
  465. package/static/dist/assets/asciidoc-lx0cuujr.js +1 -0
  466. package/static/dist/assets/asm-j5diz3sz.js +1 -0
  467. package/static/dist/assets/astro-g77i97cb.js +1 -0
  468. package/static/dist/assets/aurora-x-h2hngdsl.js +1 -0
  469. package/static/dist/assets/awk-fecghegf.js +1 -0
  470. package/static/dist/assets/ayu-dark-nvvuggz9.js +1 -0
  471. package/static/dist/assets/ayu-light-k5fxgplt.js +1 -0
  472. package/static/dist/assets/ayu-mirage-gltrvhcx.js +1 -0
  473. package/static/dist/assets/ballerina-hk9oga18.js +1 -0
  474. package/static/dist/assets/bat-ghs7lag5.js +1 -0
  475. package/static/dist/assets/beancount-pc6q2dmq.js +1 -0
  476. package/static/dist/assets/berry-l96jp8n4.js +1 -0
  477. package/static/dist/assets/bibtex-jxn7maz2.js +1 -0
  478. package/static/dist/assets/bicep-i1yv3ngd.js +1 -0
  479. package/static/dist/assets/bird2-k3aagqn0.js +1 -0
  480. package/static/dist/assets/blade-boo0u92y.js +1 -0
  481. package/static/dist/assets/blockDiagram-I7D4REHJ-hd3gw0cj.js +129 -0
  482. package/static/dist/assets/bsl-f8m1ja7w.js +1 -0
  483. package/static/dist/assets/c-cat0w3sc.js +1 -0
  484. package/static/dist/assets/c3-j6ile59o.js +1 -0
  485. package/static/dist/assets/c4Diagram-7LVT6UL2-jlmbjiji.js +38 -0
  486. package/static/dist/assets/cadence-e3x2pgsu.js +1 -0
  487. package/static/dist/assets/cairo-mblac9dt.js +1 -0
  488. package/static/dist/assets/catppuccin-frappe-dj7qsd4s.js +1 -0
  489. package/static/dist/assets/catppuccin-latte-oh2bx7qn.js +1 -0
  490. package/static/dist/assets/catppuccin-macchiato-m3xyazph.js +1 -0
  491. package/static/dist/assets/catppuccin-mocha-m3rjj89j.js +1 -0
  492. package/static/dist/assets/channel-ix8cxdld.js +1 -0
  493. package/static/dist/assets/chunk-2Q5K7J3B-k08c29qw.js +1 -0
  494. package/static/dist/assets/chunk-4HAMMTFA-oydbpsin.js +62 -0
  495. package/static/dist/assets/chunk-5VM5RSS4-br0zxsux.js +15 -0
  496. package/static/dist/assets/chunk-75Z2AOVW-j633otj1.js +2 -0
  497. package/static/dist/assets/chunk-DU6HZSFF-ods2l027.js +128 -0
  498. package/static/dist/assets/chunk-F27PBJKO-ln4n2cwt.js +1 -0
  499. package/static/dist/assets/chunk-FOHPRMQF-opuflp73.js +161 -0
  500. package/static/dist/assets/chunk-GMAD6QVW-fpz133eh.js +72 -0
  501. package/static/dist/assets/chunk-GVQU2GXP-abs9ixiy.js +1 -0
  502. package/static/dist/assets/chunk-IMKFNOWR-j9vukdy1.js +231 -0
  503. package/static/dist/assets/chunk-JWPE2WC7-mw03m5s9.js +1 -0
  504. package/static/dist/assets/chunk-L3NEJ4N5-cfyw87r3.js +1 -0
  505. package/static/dist/assets/chunk-OSK3NFVY-baja78wr.js +10 -0
  506. package/static/dist/assets/chunk-P2QGCYS3-g66xby8h.js +1 -0
  507. package/static/dist/assets/chunk-POPQ4Y6H-osqu864t.js +1 -0
  508. package/static/dist/assets/chunk-PWAF6VOD-egejasv1.js +1 -0
  509. package/static/dist/assets/chunk-SHT3W25Y-l014h8zz.js +168 -0
  510. package/static/dist/assets/chunk-SVP7TREG-n3z10bp3.js +88 -0
  511. package/static/dist/assets/chunk-TICWLB2K-bzozkjc0.js +206 -0
  512. package/static/dist/assets/chunk-XXDRQBXY-n40pf9vy.js +1 -0
  513. package/static/dist/assets/chunk-Y2CYZVJY-n9gs7k4d.js +1 -0
  514. package/static/dist/assets/clarity-bdn1d8fx.js +1 -0
  515. package/static/dist/assets/classDiagram-ZZMXUADV-c210y3il.js +1 -0
  516. package/static/dist/assets/classDiagram-v2-VYDZK3BY-c210y3il.js +1 -0
  517. package/static/dist/assets/clojure-n5b9o4lq.js +1 -0
  518. package/static/dist/assets/cmake-f68p68h5.js +1 -0
  519. package/static/dist/assets/cobol-go622aep.js +1 -0
  520. package/static/dist/assets/codeowners-lgfjmw2s.js +1 -0
  521. package/static/dist/assets/codeql-cojlysyb.js +1 -0
  522. package/static/dist/assets/coffee-jwo1xjhq.js +1 -0
  523. package/static/dist/assets/common-lisp-ko58h8pe.js +1 -0
  524. package/static/dist/assets/copied-cjsttec1.js +1 -0
  525. package/static/dist/assets/coq-gns70ukp.js +1 -0
  526. package/static/dist/assets/cose-bilkent-JH36ORCC-eclcy6ja.js +1 -0
  527. package/static/dist/assets/cpp-nre7j0kq.js +1 -0
  528. package/static/dist/assets/crystal-lviso2je.js +1 -0
  529. package/static/dist/assets/csharp-kkz9hcxp.js +1 -0
  530. package/static/dist/assets/css-ywz9j4hb.js +1 -0
  531. package/static/dist/assets/csv-ol0sxk26.js +1 -0
  532. package/static/dist/assets/cue-h5naoluy.js +1 -0
  533. package/static/dist/assets/cynefin-OW5HDTMX-elpt7h1j.js +1 -0
  534. package/static/dist/assets/cynefinDiagram-5FMLGOSQ-5mzl5pi2.js +62 -0
  535. package/static/dist/assets/cypher-j2an42no.js +1 -0
  536. package/static/dist/assets/cytoscape.esm-bqu53u12.js +321 -0
  537. package/static/dist/assets/d-crxkca3p.js +1 -0
  538. package/static/dist/assets/dagre-GXQ25YYZ-ihwlhmfl.js +4 -0
  539. package/static/dist/assets/dagre-lkoknbjn.js +1 -0
  540. package/static/dist/assets/dark-plus-kin19s9x.js +1 -0
  541. package/static/dist/assets/dart-nsg0xvqh.js +1 -0
  542. package/static/dist/assets/dax-f82777dv.js +1 -0
  543. package/static/dist/assets/defaultLocale-eeoev87l.js +1 -0
  544. package/static/dist/assets/desktop-nvg88bea.js +1 -0
  545. package/static/dist/assets/diagram-S7CK7UJ4-4z90agaz.js +30 -0
  546. package/static/dist/assets/diagram-UQ7AKVKN-eifw0lg7.js +41 -0
  547. package/static/dist/assets/diagram-VSXAHHWV-ksh3sjqv.js +3 -0
  548. package/static/dist/assets/diagram-VX7I27RA-ett72f71.js +24 -0
  549. package/static/dist/assets/diagram-Z3DM3KII-l8scp8nu.js +24 -0
  550. package/static/dist/assets/diff-c5xjoml2.js +1 -0
  551. package/static/dist/assets/dist-c4c2m3kv.js +1 -0
  552. package/static/dist/assets/docker-s0pf2u92.js +1 -0
  553. package/static/dist/assets/dotenv-d2gvqxc1.js +1 -0
  554. package/static/dist/assets/dracula-eicfho73.js +1 -0
  555. package/static/dist/assets/dracula-soft-doslejd2.js +1 -0
  556. package/static/dist/assets/dream-maker-mz8d3pqb.js +1 -0
  557. package/static/dist/assets/ebnfDiagram-PWID7BFC-f0pxcmit.js +1 -0
  558. package/static/dist/assets/edge-dvv35byi.js +1 -0
  559. package/static/dist/assets/elixir-i2f1ki1g.js +1 -0
  560. package/static/dist/assets/elm-cpepyjm4.js +1 -0
  561. package/static/dist/assets/emacs-lisp-lhl63kmy.js +1 -0
  562. package/static/dist/assets/endpoints-ipnv1hd4.js +64 -0
  563. package/static/dist/assets/erDiagram-RLTQ6QDP-f47m5xh0.js +99 -0
  564. package/static/dist/assets/erb-idlyfheg.js +1 -0
  565. package/static/dist/assets/erlang-kbk8e1kh.js +1 -0
  566. package/static/dist/assets/eventmodeling-NTZA5JFV-d9b5a0ia.js +1 -0
  567. package/static/dist/assets/everforest-dark-cv4maom7.js +1 -0
  568. package/static/dist/assets/everforest-light-njdw7fx6.js +1 -0
  569. package/static/dist/assets/fennel-mm8r79co.js +1 -0
  570. package/static/dist/assets/fish-em0xdaat.js +1 -0
  571. package/static/dist/assets/flowDiagram-HODETNUW-kfxxsyrk.js +1 -0
  572. package/static/dist/assets/fluent-kzq1mil2.js +1 -0
  573. package/static/dist/assets/fortran-fixed-form-lwddxd99.js +1 -0
  574. package/static/dist/assets/fortran-free-form-jao3bzvo.js +1 -0
  575. package/static/dist/assets/fsharp-ouam7w4k.js +1 -0
  576. package/static/dist/assets/ganttDiagram-EL5Y4UJY-bmktjdi0.js +292 -0
  577. package/static/dist/assets/gdresource-gawivel9.js +1 -0
  578. package/static/dist/assets/gdscript-kcamxf4c.js +1 -0
  579. package/static/dist/assets/gdshader-hx54new5.js +1 -0
  580. package/static/dist/assets/genie-i5n3m91v.js +1 -0
  581. package/static/dist/assets/gherkin-lxn181dy.js +1 -0
  582. package/static/dist/assets/git-commit-e6qgtuh5.js +1 -0
  583. package/static/dist/assets/git-rebase-d9lpfpbn.js +1 -0
  584. package/static/dist/assets/gitGraph-4MIJSDKK-j2ueg258.js +1 -0
  585. package/static/dist/assets/gitGraphDiagram-WWUBYQGX-ms6586v9.js +106 -0
  586. package/static/dist/assets/github-dark-default-m0qs6qki.js +1 -0
  587. package/static/dist/assets/github-dark-dimmed-g0vz4qee.js +1 -0
  588. package/static/dist/assets/github-dark-high-contrast-hugubo52.js +1 -0
  589. package/static/dist/assets/github-dark-ljlyim8s.js +1 -0
  590. package/static/dist/assets/github-light-default-fgfak5mv.js +1 -0
  591. package/static/dist/assets/github-light-high-contrast-hka6wb3r.js +1 -0
  592. package/static/dist/assets/github-light-jhyi45t4.js +1 -0
  593. package/static/dist/assets/gleam-ix1dym3g.js +1 -0
  594. package/static/dist/assets/glimmer-js-39i0urfb.js +1 -0
  595. package/static/dist/assets/glimmer-ts-gdtd6n73.js +1 -0
  596. package/static/dist/assets/glsl-o1djm5pp.js +1 -0
  597. package/static/dist/assets/gn-cbzhsgl9.js +1 -0
  598. package/static/dist/assets/gnuplot-dr8f9gvm.js +1 -0
  599. package/static/dist/assets/go-enhtrrw8.js +1 -0
  600. package/static/dist/assets/graphlib-mrng1xrk.js +1 -0
  601. package/static/dist/assets/graphql-kj6rz55t.js +1 -0
  602. package/static/dist/assets/groovy-jff59t9e.js +1 -0
  603. package/static/dist/assets/gruvbox-dark-hard-lgsj7y5r.js +1 -0
  604. package/static/dist/assets/gruvbox-dark-medium-ezt86wrc.js +1 -0
  605. package/static/dist/assets/gruvbox-dark-soft-1a3jfdlm.js +1 -0
  606. package/static/dist/assets/gruvbox-light-hard-d82lddjc.js +1 -0
  607. package/static/dist/assets/gruvbox-light-medium-d3ffitv3.js +1 -0
  608. package/static/dist/assets/gruvbox-light-soft-e5gf7i2q.js +1 -0
  609. package/static/dist/assets/hack-pe1qqr2i.js +1 -0
  610. package/static/dist/assets/haml-cknnbcqs.js +1 -0
  611. package/static/dist/assets/handlebars-hwq64orh.js +1 -0
  612. package/static/dist/assets/haskell-o7nor2z2.js +1 -0
  613. package/static/dist/assets/haxe-4rwdh42h.js +1 -0
  614. package/static/dist/assets/hcl-nnng763h.js +1 -0
  615. package/static/dist/assets/highlighted-body-KPVGNVTW-ev52d2si.js +1 -0
  616. package/static/dist/assets/hjson-kscwmuzk.js +1 -0
  617. package/static/dist/assets/hlsl-kopkvwox.js +1 -0
  618. package/static/dist/assets/horizon-bright-gn4aqinx.js +1 -0
  619. package/static/dist/assets/horizon-h5nzrwlb.js +1 -0
  620. package/static/dist/assets/houston-kifsbmbx.js +1 -0
  621. package/static/dist/assets/html-derivative-h2i2pyjc.js +1 -0
  622. package/static/dist/assets/html-ha05xtvt.js +1 -0
  623. package/static/dist/assets/http-cf94zu27.js +1 -0
  624. package/static/dist/assets/hurl-lslax568.js +1 -0
  625. package/static/dist/assets/hxml-g52gxet6.js +1 -0
  626. package/static/dist/assets/hy-jc9www1l.js +1 -0
  627. package/static/dist/assets/imba-n9x1ej2f.js +1 -0
  628. package/static/dist/assets/index-bz7g7rhx.css +2 -0
  629. package/static/dist/assets/index-hywfjw88.js +11 -0
  630. package/static/dist/assets/info-A6RAGUB7-j717vyt7.js +1 -0
  631. package/static/dist/assets/infoDiagram-27XIBGKW-dsbpib36.js +2 -0
  632. package/static/dist/assets/ini-hg6eosim.js +1 -0
  633. package/static/dist/assets/init-ljpdkjra.js +1 -0
  634. package/static/dist/assets/ishikawaDiagram-5VMMS53U-n0sz3i2d.js +70 -0
  635. package/static/dist/assets/java-ndjf2o89.js +1 -0
  636. package/static/dist/assets/javascript-coftlwy3.js +1 -0
  637. package/static/dist/assets/jinja-etei9wy7.js +1 -0
  638. package/static/dist/assets/jison-hyekgft1.js +1 -0
  639. package/static/dist/assets/journeyDiagram-3NMN7TZE-mcxz1mme.js +139 -0
  640. package/static/dist/assets/json-lok0yaho.js +1 -0
  641. package/static/dist/assets/json5-e4tr07tg.js +1 -0
  642. package/static/dist/assets/jsonc-jbmkhoep.js +1 -0
  643. package/static/dist/assets/jsonl-j35ke6at.js +1 -0
  644. package/static/dist/assets/jsonnet-iewuy86o.js +1 -0
  645. package/static/dist/assets/jssm-m1449zlc.js +1 -0
  646. package/static/dist/assets/jsx-b64w0nbx.js +1 -0
  647. package/static/dist/assets/jsx-runtime-eu92a5pu.js +1 -0
  648. package/static/dist/assets/julia-jxxzz2yn.js +1 -0
  649. package/static/dist/assets/just-mc29iw9t.js +1 -0
  650. package/static/dist/assets/kanagawa-dragon-i9mmmgud.js +1 -0
  651. package/static/dist/assets/kanagawa-lotus-ev5oro17.js +1 -0
  652. package/static/dist/assets/kanagawa-wave-i06560uw.js +1 -0
  653. package/static/dist/assets/kanban-definition-UXKFOSKX-n6hq2lyc.js +89 -0
  654. package/static/dist/assets/kdl-kgzv1x9e.js +1 -0
  655. package/static/dist/assets/kotlin-nmx05b3f.js +1 -0
  656. package/static/dist/assets/kusto-fawmdms4.js +1 -0
  657. package/static/dist/assets/laserwave-goebpayr.js +1 -0
  658. package/static/dist/assets/latex-pafa03ft.js +1 -0
  659. package/static/dist/assets/lazyRouteComponent-faquioun.js +1 -0
  660. package/static/dist/assets/lean-jom31nm3.js +1 -0
  661. package/static/dist/assets/less-mwvscr3d.js +1 -0
  662. package/static/dist/assets/light-plus-mws1g85f.js +1 -0
  663. package/static/dist/assets/line-h5xq20s4.js +1 -0
  664. package/static/dist/assets/linear-becwlnhk.js +1 -0
  665. package/static/dist/assets/link-ib4prsn5.js +1 -0
  666. package/static/dist/assets/liquid-hz5c2pov.js +1 -0
  667. package/static/dist/assets/llvm-j5wmr3g9.js +1 -0
  668. package/static/dist/assets/log-eur4gurm.js +1 -0
  669. package/static/dist/assets/login-mvjys1ol.js +1 -0
  670. package/static/dist/assets/logo-j3h8r0pu.js +1 -0
  671. package/static/dist/assets/lua-leyf8mlb.js +1 -0
  672. package/static/dist/assets/luau-im5d6q8k.js +1 -0
  673. package/static/dist/assets/make-npl27xqy.js +1 -0
  674. package/static/dist/assets/markdown-fibv6lrm.js +1 -0
  675. package/static/dist/assets/marko-cn1fzpdv.js +1 -0
  676. package/static/dist/assets/matchContext-f8oy3lo7.js +1 -0
  677. package/static/dist/assets/material-theme-darker-dhm8zmok.js +1 -0
  678. package/static/dist/assets/material-theme-gdimc61s.js +1 -0
  679. package/static/dist/assets/material-theme-lighter-c1fszbb2.js +1 -0
  680. package/static/dist/assets/material-theme-ocean-iakojpmy.js +1 -0
  681. package/static/dist/assets/material-theme-palenight-hgxmykmi.js +1 -0
  682. package/static/dist/assets/matlab-o6nvvbf2.js +1 -0
  683. package/static/dist/assets/mdc-huhy88df.js +1 -0
  684. package/static/dist/assets/mdx-mmgeh26h.js +1 -0
  685. package/static/dist/assets/mermaid-HWGCJPDP-gmnkgf1n.js +1 -0
  686. package/static/dist/assets/mermaid-f9ad87lb.js +1 -0
  687. package/static/dist/assets/mermaid-parser.core-n9cuu5ue.js +7 -0
  688. package/static/dist/assets/min-dark-e5sicuw2.js +1 -0
  689. package/static/dist/assets/min-light-gst87fvf.js +1 -0
  690. package/static/dist/assets/mindmap-definition-YA3MSWOX-gta3u7z4.js +96 -0
  691. package/static/dist/assets/mipsasm-etoqqos6.js +1 -0
  692. package/static/dist/assets/mojo-fyyk0b1z.js +1 -0
  693. package/static/dist/assets/monokai-jl389a9o.js +1 -0
  694. package/static/dist/assets/moonbit-je86hbgx.js +1 -0
  695. package/static/dist/assets/move-g7w7k042.js +1 -0
  696. package/static/dist/assets/narrat-d1cszt6i.js +1 -0
  697. package/static/dist/assets/nextflow-fpd3eqgm.js +1 -0
  698. package/static/dist/assets/nextflow-groovy-nc95p6pm.js +1 -0
  699. package/static/dist/assets/nginx-e7lvhsmn.js +1 -0
  700. package/static/dist/assets/night-owl-light-b2j1bc8t.js +1 -0
  701. package/static/dist/assets/night-owl-nm3cgqfv.js +1 -0
  702. package/static/dist/assets/nim-dun5d8mk.js +1 -0
  703. package/static/dist/assets/nix-sxazvl0w.js +1 -0
  704. package/static/dist/assets/nord-jiiendyo.js +1 -0
  705. package/static/dist/assets/not-found-ccnnac39.js +1 -0
  706. package/static/dist/assets/nushell-nbi9xmdg.js +1 -0
  707. package/static/dist/assets/objective-c-oshe4ycx.js +1 -0
  708. package/static/dist/assets/objective-cpp-go29ofq1.js +1 -0
  709. package/static/dist/assets/ocaml-56kivtnr.js +1 -0
  710. package/static/dist/assets/odin-g772bhi5.js +1 -0
  711. package/static/dist/assets/onboarding-l6quy6gz.js +1 -0
  712. package/static/dist/assets/one-dark-pro-ext74l87.js +1 -0
  713. package/static/dist/assets/one-light-o5mlsn8i.js +1 -0
  714. package/static/dist/assets/openscad-e9e9mfyg.js +1 -0
  715. package/static/dist/assets/ordinal-d88pfdla.js +1 -0
  716. package/static/dist/assets/packet-AYTQ26CC-bpzuq5n6.js +1 -0
  717. package/static/dist/assets/pascal-dmg2rs6d.js +1 -0
  718. package/static/dist/assets/passkeys-ktie3sr0.js +1 -0
  719. package/static/dist/assets/path-b509aej0.js +1 -0
  720. package/static/dist/assets/pegDiagram-XKGWAZYB-juye13e5.js +1 -0
  721. package/static/dist/assets/perl-bj3oqtet.js +1 -0
  722. package/static/dist/assets/php-buzp12r0.js +1 -0
  723. package/static/dist/assets/pie-WAS4IAKB-odhb8buq.js +1 -0
  724. package/static/dist/assets/pieDiagram-E7YTZNPT-mgb14ksh.js +39 -0
  725. package/static/dist/assets/pkl-co2grztk.js +1 -0
  726. package/static/dist/assets/plastic-mm7c7uq7.js +1 -0
  727. package/static/dist/assets/plsql-l0i9f33n.js +1 -0
  728. package/static/dist/assets/po-f3ga9osn.js +1 -0
  729. package/static/dist/assets/poimandres-mnwq5v4d.js +1 -0
  730. package/static/dist/assets/polar-ldicpe6g.js +1 -0
  731. package/static/dist/assets/postcss-fgpvnt75.js +1 -0
  732. package/static/dist/assets/powerquery-mflxo46x.js +1 -0
  733. package/static/dist/assets/powershell-oado4mxi.js +1 -0
  734. package/static/dist/assets/prepaint-f14kbd49.js +21 -0
  735. package/static/dist/assets/prisma-go1e7wq8.js +1 -0
  736. package/static/dist/assets/prolog-cbjal8aj.js +1 -0
  737. package/static/dist/assets/proto-lrhov7xc.js +1 -0
  738. package/static/dist/assets/pug-mjad7he9.js +1 -0
  739. package/static/dist/assets/puppet-h22szrmn.js +1 -0
  740. package/static/dist/assets/purescript-dwpj7hdb.js +1 -0
  741. package/static/dist/assets/python-b767fgue.js +1 -0
  742. package/static/dist/assets/qml-d1gdp10s.js +1 -0
  743. package/static/dist/assets/qmldir-lsawched.js +1 -0
  744. package/static/dist/assets/qss-lyvmg4f4.js +1 -0
  745. package/static/dist/assets/quadrantDiagram-AXDQQJYC-cg36naog.js +7 -0
  746. package/static/dist/assets/r-o3r9c7ao.js +1 -0
  747. package/static/dist/assets/racket-nbfqjw5h.js +1 -0
  748. package/static/dist/assets/radar-RG4KPBEZ-lgzfpnef.js +1 -0
  749. package/static/dist/assets/railroad-74A4TZTK-gmglc3ua.js +1 -0
  750. package/static/dist/assets/railroad-abnf-HS5TGJTU-5mjl5wpv.js +1 -0
  751. package/static/dist/assets/railroad-ebnf-LZEXJU2U-bfram8v8.js +1 -0
  752. package/static/dist/assets/railroad-peg-WCYAUIDC-nwfczn88.js +1 -0
  753. package/static/dist/assets/railroadDiagram-O6MQD6OU-cmxwjt73.js +1 -0
  754. package/static/dist/assets/raku-hcy6uwm6.js +1 -0
  755. package/static/dist/assets/razor-ilc585yr.js +1 -0
  756. package/static/dist/assets/red-if4jt303.js +1 -0
  757. package/static/dist/assets/refresh-cw-mf192q3f.js +1 -0
  758. package/static/dist/assets/reg-ivi9d1my.js +1 -0
  759. package/static/dist/assets/regexp-mpjtcvwm.js +1 -0
  760. package/static/dist/assets/rel-gqpkg3ta.js +1 -0
  761. package/static/dist/assets/requirementDiagram-BXWQKSXE-ir0s2mek.js +84 -0
  762. package/static/dist/assets/riscv-j1f2yjp2.js +1 -0
  763. package/static/dist/assets/rolldown-runtime-b9miacsj.js +1 -0
  764. package/static/dist/assets/ron-bjqasg78.js +1 -0
  765. package/static/dist/assets/root-mbklpuv4.js +1 -0
  766. package/static/dist/assets/rose-pine-dawn-nlpzqzob.js +1 -0
  767. package/static/dist/assets/rose-pine-grpwpg67.js +1 -0
  768. package/static/dist/assets/rose-pine-moon-b9yyevxr.js +1 -0
  769. package/static/dist/assets/rosmsg-hv3wcot6.js +1 -0
  770. package/static/dist/assets/rough.esm-on4k4je3.js +1 -0
  771. package/static/dist/assets/rst-jrkwjdyi.js +1 -0
  772. package/static/dist/assets/ruby-n4tjcbpz.js +1 -0
  773. package/static/dist/assets/rust-jqduclx1.js +1 -0
  774. package/static/dist/assets/sankeyDiagram-P5KCCOFB-jo7jcdq0.js +40 -0
  775. package/static/dist/assets/sas-hjo6y93k.js +1 -0
  776. package/static/dist/assets/sass-m1yncbwu.js +1 -0
  777. package/static/dist/assets/saved-g777hp1t.js +1 -0
  778. package/static/dist/assets/scala-l9ahg4e9.js +1 -0
  779. package/static/dist/assets/scheme-mlodf39l.js +1 -0
  780. package/static/dist/assets/scss-ncidjv48.js +1 -0
  781. package/static/dist/assets/sdbl-bwg2t5pt.js +1 -0
  782. package/static/dist/assets/search-i2kfogyx.js +1 -0
  783. package/static/dist/assets/sequenceDiagram-WJ2MYXX4-n0pf6xk5.js +162 -0
  784. package/static/dist/assets/settings_section_extensions_title-hgvh507l.js +1 -0
  785. package/static/dist/assets/shaderlab-be89ch6g.js +1 -0
  786. package/static/dist/assets/share._token-il3y6js2.js +2 -0
  787. package/static/dist/assets/shellscript-m8whjpqd.js +1 -0
  788. package/static/dist/assets/shellsession-i5bj6syz.js +1 -0
  789. package/static/dist/assets/sizeCapture-INFHLROL-g612l48j.js +1 -0
  790. package/static/dist/assets/slack-dark-ny9l0r7b.js +1 -0
  791. package/static/dist/assets/slack-ochin-g98102hs.js +1 -0
  792. package/static/dist/assets/sliders-horizontal-kd99ffvl.js +1 -0
  793. package/static/dist/assets/smalltalk-g9lpwisn.js +1 -0
  794. package/static/dist/assets/snazzy-light-dlu9q2m5.js +1 -0
  795. package/static/dist/assets/solarized-dark-mx1nd4sm.js +1 -0
  796. package/static/dist/assets/solarized-light-mqzd33fz.js +1 -0
  797. package/static/dist/assets/solidity-ih313ji4.js +1 -0
  798. package/static/dist/assets/soy-hhh36ysq.js +1 -0
  799. package/static/dist/assets/sparql-pewjbauq.js +1 -0
  800. package/static/dist/assets/splunk-d8q89juf.js +1 -0
  801. package/static/dist/assets/sql-j21bzcl6.js +1 -0
  802. package/static/dist/assets/src-hjyib4mu.js +1 -0
  803. package/static/dist/assets/ssh-config-fzxlymn8.js +1 -0
  804. package/static/dist/assets/stata-bbu2onh1.js +1 -0
  805. package/static/dist/assets/stateDiagram-D77RDMKH-olbrwyv9.js +1 -0
  806. package/static/dist/assets/stateDiagram-v2-MP3YSRHH-dnzlmdpu.js +1 -0
  807. package/static/dist/assets/stylus-hifjg0ye.js +1 -0
  808. package/static/dist/assets/surrealql-l5vczuco.js +1 -0
  809. package/static/dist/assets/svelte-idn422g6.js +1 -0
  810. package/static/dist/assets/swift-n11rc3v3.js +1 -0
  811. package/static/dist/assets/swimlanes-42K2YHIH-od14zrw6.js +1 -0
  812. package/static/dist/assets/swimlanesDiagram-VR7AAH4N-ck0eqqdp.js +8 -0
  813. package/static/dist/assets/synthwave-84-clkt7319.js +1 -0
  814. package/static/dist/assets/system-verilog-l8k1po2l.js +1 -0
  815. package/static/dist/assets/systemd-d1zoxedb.js +1 -0
  816. package/static/dist/assets/talonscript-j9gt5qb1.js +1 -0
  817. package/static/dist/assets/tasl-meer3lyk.js +1 -0
  818. package/static/dist/assets/tcl-jdc54rsg.js +1 -0
  819. package/static/dist/assets/templ-e22qou3c.js +1 -0
  820. package/static/dist/assets/terraform-oav3wzsy.js +1 -0
  821. package/static/dist/assets/tex-deqpc5ee.js +1 -0
  822. package/static/dist/assets/timeline-definition-24CTP7MA-l0qokmnb.js +120 -0
  823. package/static/dist/assets/todoStore-la6uyqzj.js +1 -0
  824. package/static/dist/assets/tokyo-night-cnyqlmc2.js +1 -0
  825. package/static/dist/assets/toml-jj1ee1k1.js +1 -0
  826. package/static/dist/assets/trash-bxz1k9cw.js +1 -0
  827. package/static/dist/assets/treeView-Q6P3EWNA-hma3ip8m.js +1 -0
  828. package/static/dist/assets/treemap-WGGIJYW6-bghjng5m.js +1 -0
  829. package/static/dist/assets/ts-tags-ctnibc27.js +1 -0
  830. package/static/dist/assets/tsv-cxbgj4wh.js +1 -0
  831. package/static/dist/assets/tsx-i163n32g.js +1 -0
  832. package/static/dist/assets/turtle-g1kfgpwv.js +1 -0
  833. package/static/dist/assets/twig-x0fi7wm8.js +1 -0
  834. package/static/dist/assets/typescript-g18c34xz.js +1 -0
  835. package/static/dist/assets/typespec-hokgy7ic.js +1 -0
  836. package/static/dist/assets/typst-l6lt2vta.js +1 -0
  837. package/static/dist/assets/untitled-nfaw0q7m.js +1 -0
  838. package/static/dist/assets/useForm-k7fj2zsr.js +1 -0
  839. package/static/dist/assets/useLocale-evhacmv2.js +1 -0
  840. package/static/dist/assets/useParams-gpbjxj8s.js +1 -0
  841. package/static/dist/assets/useSearch-bhdptos7.js +1 -0
  842. package/static/dist/assets/useSelector-f2aak1ol.js +1 -0
  843. package/static/dist/assets/v-lwnsi8rl.js +1 -0
  844. package/static/dist/assets/vala-db1h2kp7.js +1 -0
  845. package/static/dist/assets/vb-nrezymby.js +1 -0
  846. package/static/dist/assets/vennDiagram-4TSXK5OY-bo97zf3z.js +34 -0
  847. package/static/dist/assets/verilog-jworpiw4.js +1 -0
  848. package/static/dist/assets/vesper-o1vwtlg2.js +1 -0
  849. package/static/dist/assets/vhdl-gnn4vfnm.js +1 -0
  850. package/static/dist/assets/viml-ogfqutxv.js +1 -0
  851. package/static/dist/assets/vitesse-black-b5y62t71.js +1 -0
  852. package/static/dist/assets/vitesse-dark-fj1ju380.js +1 -0
  853. package/static/dist/assets/vitesse-light-bjycd3ha.js +1 -0
  854. package/static/dist/assets/vue-html-nskj3du0.js +1 -0
  855. package/static/dist/assets/vue-mwu5l1bb.js +1 -0
  856. package/static/dist/assets/vue-vine-cqe77smq.js +1 -0
  857. package/static/dist/assets/vyper-jsmo764l.js +1 -0
  858. package/static/dist/assets/wardley-WFR3VGLG-pbjl6jav.js +1 -0
  859. package/static/dist/assets/wardleyDiagram-VM6X3IG4-bmy9i09l.js +78 -0
  860. package/static/dist/assets/wasm-g1zrybde.js +1 -0
  861. package/static/dist/assets/wasm-gezzbmz0.js +1 -0
  862. package/static/dist/assets/wenyan-lgcd7t1n.js +1 -0
  863. package/static/dist/assets/wgsl-gotoh48n.js +1 -0
  864. package/static/dist/assets/wikitext-j1379ez7.js +1 -0
  865. package/static/dist/assets/wit-neu67rwu.js +1 -0
  866. package/static/dist/assets/wolfram-mbb1p6oi.js +1 -0
  867. package/static/dist/assets/xml-gau7gvrv.js +1 -0
  868. package/static/dist/assets/xsl-ew09zq8b.js +1 -0
  869. package/static/dist/assets/xychartDiagram-S5SC5T6Z-eercu0mc.js +7 -0
  870. package/static/dist/assets/yaml-ofnrxtvf.js +1 -0
  871. package/static/dist/assets/zenscript-ge1h0r83.js +1 -0
  872. package/static/dist/assets/zig-ik06evde.js +1 -0
  873. package/static/dist/extension-sdk.js +1 -0
  874. package/static/dist/index.html +1 -0
  875. package/static/dist/manifest.webmanifest +29 -0
  876. package/static/dist/sw.js +944 -0
@@ -0,0 +1,836 @@
1
+ /**
2
+ * OIDC login (browser code flow and the native app handoff), byte-compatible
3
+ * with Python `api/auth_oidc.py`: operator config (`webui_oidc` in the base
4
+ * home config.yaml or `HERMES_WEBUI_OIDC_*`), PKCE S256, discovery/JWKS caches,
5
+ * RS/ES JWT verification through `node:crypto`, allow/owner/profile policies,
6
+ * and the session fingerprint = sha256(canonical policy JSON).
7
+ */
8
+ import { readCapped } from '../http/capped.js';
9
+ import { isNonGlobalAddress } from '../http/addresses.js';
10
+ import { BlockedAddressError, vettedAddresses } from '../http/pinned.js';
11
+ import { createHash, createPublicKey, randomBytes, timingSafeEqual, verify as cryptoVerify } from 'node:crypto';
12
+ import { existsSync, statSync } from 'node:fs';
13
+ import { isIP } from 'node:net';
14
+ import { ConfigUnavailable } from '../config/agent-config.js';
15
+ import { isDict } from '../config/agent-config.js';
16
+ import { str } from '../util.js';
17
+ export class OidcConfigError extends Error {
18
+ nativeFlowId = null;
19
+ }
20
+ export class OidcAuthError extends Error {
21
+ status;
22
+ nativeFlowId = null;
23
+ constructor(message, status = 401) {
24
+ super(message);
25
+ this.status = status;
26
+ }
27
+ }
28
+ const DEFAULT_SCOPES = ['openid', 'profile', 'email'];
29
+ const PENDING_TTL_S = 600;
30
+ const MAX_PENDING = 128;
31
+ const CLOCK_SKEW_S = 60;
32
+ const CACHE_TTL_S = 300;
33
+ const NATIVE_FLOW_TTL_S = 600;
34
+ const NATIVE_EXCHANGE_TTL_S = 60;
35
+ const NATIVE_CALLBACK_HOST = 'oidc-callback';
36
+ const NATIVE_CALLBACK_SCHEMES = new Set(['talaria', 'talaria-branch']);
37
+ const NATIVE_VALUE_RE = /^[A-Za-z0-9._~-]{16,256}$/;
38
+ const PKCE_CHALLENGE_RE = /^[A-Za-z0-9_-]{43}$/;
39
+ const PKCE_VERIFIER_RE = /^[A-Za-z0-9._~-]{43,128}$/;
40
+ const UNRESOLVED_RE = /\$\{[^}]+\}/;
41
+ const OWNER_POLICY_ERROR = 'webui_oidc.owner_claim and owner_values must both be set to a claim path and a non-empty list of strings; the OIDC owner allowlist matches nobody until they are';
42
+ export const b64u = (data) => data.toString('base64url');
43
+ export const b64uDecode = (data) => Buffer.from(data, 'base64url');
44
+ const safeEq = (a, b) => { const x = Buffer.from(a, 'utf8'); const y = Buffer.from(b, 'utf8'); return x.length === y.length && timingSafeEqual(x, y); };
45
+ function textList(raw) {
46
+ if (raw === null || raw === undefined)
47
+ return [];
48
+ if (Array.isArray(raw))
49
+ return raw.map((v) => str(v).trim()).filter(Boolean);
50
+ return str(raw).replaceAll('\n', ',').split(',').flatMap((part) => part.split(/\s+/)).map((v) => v.trim()).filter(Boolean);
51
+ }
52
+ function allowValues(raw) {
53
+ if (raw === null || raw === undefined)
54
+ return [];
55
+ const values = Array.isArray(raw) ? raw.map((v) => str(v).trim()).filter(Boolean) : str(raw).replaceAll('\n', ',').split(',').map((v) => v.trim()).filter(Boolean);
56
+ return values.some((v) => UNRESOLVED_RE.test(v)) ? [] : values;
57
+ }
58
+ /** Non-global destinations never receive the client credentials (`http/addresses.ts`). */
59
+ const disallowedIp = isNonGlobalAddress;
60
+ export function safeNextPath(raw) {
61
+ const path = str(raw).trim();
62
+ if (!path.startsWith('/') || path.startsWith('//') || path.startsWith('/\\'))
63
+ return '/';
64
+ if (/[\x00-\x1f\x7f\s]/.test(path))
65
+ return '/';
66
+ return path;
67
+ }
68
+ /** Python `_normalize_server_origin`. */
69
+ export function normalizeServerOrigin(raw) {
70
+ let u;
71
+ try {
72
+ u = new URL(str(raw).trim());
73
+ }
74
+ catch {
75
+ throw new OidcAuthError('Invalid native OIDC server identity', 400);
76
+ }
77
+ const scheme = u.protocol.replace(':', '').toLowerCase();
78
+ if (!['http', 'https'].includes(scheme) || !u.hostname || u.username || u.password || (u.pathname !== '/' && u.pathname !== '') || u.search || u.hash)
79
+ throw new OidcAuthError('Invalid native OIDC server identity', 400);
80
+ const host = u.hostname.toLowerCase();
81
+ const display = host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
82
+ const port = u.port;
83
+ return `${scheme}://${display}${port ? `:${port}` : ''}`;
84
+ }
85
+ function validateNativeCallback(raw) {
86
+ const value = str(raw).trim();
87
+ const m = /^([a-z][a-z0-9+.-]{1,63}):\/\/([^/?#]*)(.*)$/i.exec(value);
88
+ if (!m)
89
+ throw new OidcAuthError('Invalid native OIDC callback URL', 400);
90
+ const scheme = (m[1] ?? '').toLowerCase();
91
+ const netloc = m[2] ?? '';
92
+ const rest = m[3] ?? '';
93
+ if (!NATIVE_CALLBACK_SCHEMES.has(scheme) || netloc.toLowerCase() !== NATIVE_CALLBACK_HOST || (rest !== '' && rest !== '/'))
94
+ throw new OidcAuthError('Invalid native OIDC callback URL', 400);
95
+ return `${scheme}://${netloc.toLowerCase()}`;
96
+ }
97
+ function serverIdentity(origin) {
98
+ return b64u(createHash('sha256').update(origin, 'utf8').digest());
99
+ }
100
+ export function claimPath(claims, dotted) {
101
+ let current = claims;
102
+ for (const part of dotted.split('.')) {
103
+ if (!isDict(current) || !(part in current))
104
+ return undefined;
105
+ current = current[part];
106
+ }
107
+ return current;
108
+ }
109
+ function claimValues(value) {
110
+ if (Array.isArray(value))
111
+ return new Set(value.map((v) => str(v)).filter((v) => v.trim()));
112
+ if (isDict(value))
113
+ return new Set(Object.values(value).map((v) => str(v)).filter((v) => v.trim()));
114
+ const text = str(value).trim();
115
+ return text ? new Set([text]) : new Set();
116
+ }
117
+ export class OidcService {
118
+ deps;
119
+ pending = new Map();
120
+ nativeFlows = new Map();
121
+ exchanges = new Map();
122
+ discovery = new Map();
123
+ jwks = new Map();
124
+ lastConfig = null;
125
+ lastConfigAt = 0;
126
+ warnedOwnerPolicy = false;
127
+ constructor(deps) {
128
+ this.deps = deps;
129
+ }
130
+ /** Python `is_oidc_enabled` on the last resolved config (sync for the auth gate). */
131
+ enabledSync() {
132
+ const cfg = this.lastConfig;
133
+ if (!cfg)
134
+ return false;
135
+ if (cfg.config_read_failed)
136
+ return true;
137
+ return Boolean(cfg.issuer && cfg.client_id && cfg.allow_claim && cfg.allow_values.length);
138
+ }
139
+ async enabled() {
140
+ await this.resolve();
141
+ return this.enabledSync();
142
+ }
143
+ /** Python `_resolve_oidc_config`, cached for 5 s. */
144
+ async resolve() {
145
+ if (this.lastConfig && this.deps.now() - this.lastConfigAt < 5)
146
+ return this.lastConfig;
147
+ const env = this.deps.env;
148
+ let raw = {};
149
+ let readFailed = false;
150
+ try {
151
+ const cfg = await this.deps.operatorConfig();
152
+ const value = cfg.webui_oidc;
153
+ if (isDict(value))
154
+ raw = this.expandEnv(value);
155
+ else if (value !== null && value !== undefined)
156
+ throw new OidcConfigError('webui_oidc must be a mapping');
157
+ }
158
+ catch (error) {
159
+ if (error instanceof ConfigUnavailable && this.lastConfig)
160
+ return this.lastConfig;
161
+ // No last-known config to fall back on: the auth policy is unknown, so the gate stays closed (config_read_failed
162
+ // reports OIDC as enabled and refuses login) until the operator config can be read; the 5 s cache retries.
163
+ readFailed = true;
164
+ if (error instanceof ConfigUnavailable)
165
+ this.deps.log('[oidc] operator config unavailable while the sidecar is down; failing closed until it is readable');
166
+ }
167
+ const pick = (name, envName) => (env[envName] ?? raw[name]);
168
+ const scopesRaw = textList(pick('scopes', 'HERMES_WEBUI_OIDC_SCOPES'));
169
+ const scopes = scopesRaw.length ? [...new Set(scopesRaw.includes('openid') ? scopesRaw : ['openid', ...scopesRaw])] : [...DEFAULT_SCOPES];
170
+ const [profileMap, profileMapError, profileMapConfigured] = this.normalizeProfileMap(pick('profile_map', 'HERMES_WEBUI_OIDC_PROFILE_MAP'));
171
+ const ownerClaimRaw = env.HERMES_WEBUI_OIDC_OWNER_CLAIM ?? ('owner_claim' in raw ? raw.owner_claim : undefined);
172
+ const ownerValuesRaw = env.HERMES_WEBUI_OIDC_OWNER_VALUES ?? ('owner_values' in raw ? raw.owner_values : undefined);
173
+ const ownerConfigured = ownerClaimRaw !== undefined || ownerValuesRaw !== undefined;
174
+ let ownerClaim = '';
175
+ let ownerValues = [];
176
+ let ownerError = null;
177
+ if (ownerConfigured) {
178
+ ownerClaim = typeof ownerClaimRaw === 'string' ? ownerClaimRaw.trim() : '';
179
+ if (typeof ownerValuesRaw === 'string')
180
+ ownerValues = ownerValuesRaw.replaceAll('\n', ',').split(',').map((v) => v.trim()).filter(Boolean);
181
+ else if (Array.isArray(ownerValuesRaw) && ownerValuesRaw.every((v) => typeof v === 'string' && v.trim()))
182
+ ownerValues = ownerValuesRaw.map((v) => str(v).trim());
183
+ if (ownerValues.some((v) => UNRESOLVED_RE.test(v)))
184
+ ownerValues = [];
185
+ if (!ownerClaim || !ownerValues.length || UNRESOLVED_RE.test(ownerClaim)) {
186
+ ownerValues = [];
187
+ ownerError = OWNER_POLICY_ERROR;
188
+ }
189
+ if (ownerError && !this.warnedOwnerPolicy) {
190
+ this.warnedOwnerPolicy = true;
191
+ this.deps.log(`[oidc] ${ownerError}`);
192
+ }
193
+ }
194
+ const rawProfileClaim = str(pick('profile_claim', 'HERMES_WEBUI_OIDC_PROFILE_CLAIM') || 'sub').trim();
195
+ const profileClaim = UNRESOLVED_RE.test(rawProfileClaim) ? '' : rawProfileClaim;
196
+ const allowClaim = str(pick('allow_claim', 'HERMES_WEBUI_OIDC_ALLOW_CLAIM')).trim();
197
+ const cfg = {
198
+ issuer: str(pick('issuer', 'HERMES_WEBUI_OIDC_ISSUER')).trim(), client_id: str(pick('client_id', 'HERMES_WEBUI_OIDC_CLIENT_ID')).trim(), client_secret: str(pick('client_secret', 'HERMES_WEBUI_OIDC_CLIENT_SECRET')).trim(),
199
+ redirect_uri: str(pick('redirect_uri', 'HERMES_WEBUI_OIDC_REDIRECT_URI')).trim(), scopes, allow_claim: UNRESOLVED_RE.test(allowClaim) ? '' : allowClaim, allow_values: allowValues(pick('allow_values', 'HERMES_WEBUI_OIDC_ALLOW_VALUES')),
200
+ trusted_private_hosts: this.trustedHosts(pick('trusted_private_hosts', 'HERMES_WEBUI_OIDC_TRUSTED_PRIVATE_HOSTS')), profile_claim: profileClaim, profile_map: profileMap, profile_map_configured: profileMapConfigured,
201
+ profile_map_error: profileMapError ?? (profileClaim ? null : 'webui_oidc.profile_claim could not be resolved; it still contains an unexpanded ${...} reference'),
202
+ owner_claim: ownerClaim, owner_values: ownerValues, owner_policy_configured: ownerConfigured, owner_policy_error: ownerError, config_read_failed: readFailed,
203
+ };
204
+ this.lastConfig = cfg;
205
+ this.lastConfigAt = this.deps.now();
206
+ return cfg;
207
+ }
208
+ expandEnv(obj) {
209
+ if (typeof obj === 'string')
210
+ return obj.replace(/\$\{([^}]+)\}/g, (whole, name) => { return this.deps.env[name.trim()] ?? whole; });
211
+ if (Array.isArray(obj))
212
+ return obj.map((v) => this.expandEnv(v));
213
+ if (isDict(obj))
214
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, this.expandEnv(v)]));
215
+ return obj;
216
+ }
217
+ normalizeProfileMap(raw) {
218
+ if (raw === null || raw === undefined || raw === '')
219
+ return [null, null, false];
220
+ let value = raw;
221
+ if (typeof raw === 'string') {
222
+ try {
223
+ value = JSON.parse(raw);
224
+ }
225
+ catch {
226
+ return [null, 'webui_oidc.profile_map must be a JSON object', true];
227
+ }
228
+ }
229
+ if (!isDict(value))
230
+ return [null, 'webui_oidc.profile_map must be an object', true];
231
+ const map = {};
232
+ for (const [k, v] of Object.entries(value)) {
233
+ const claim = k.trim();
234
+ const profile = str(v).trim();
235
+ if (!claim || !profile)
236
+ return [null, 'webui_oidc.profile_map entries must have non-empty claim values and profiles', true];
237
+ map[claim] = profile;
238
+ }
239
+ return [map, null, true];
240
+ }
241
+ trustedHosts(raw) {
242
+ const out = [];
243
+ for (const value of textList(raw)) {
244
+ const host = value.toLowerCase().replace(/\.+$/, '');
245
+ if (!host || host === 'localhost' || isIP(host) || /[:/\\@*]/.test(host))
246
+ continue;
247
+ if (!host.split('.').every((l) => l && l.length <= 63 && !l.startsWith('-') && !l.endsWith('-') && /^[a-z0-9-]+$/i.test(l)))
248
+ continue;
249
+ if (!out.includes(host))
250
+ out.push(host);
251
+ }
252
+ return out;
253
+ }
254
+ async require() {
255
+ const cfg = await this.resolve();
256
+ if (cfg.config_read_failed)
257
+ throw new OidcConfigError('The operator config could not be resolved; OIDC login is unavailable until it is readable');
258
+ if (!cfg.issuer || !cfg.client_id)
259
+ throw new OidcConfigError('Native OIDC login is not configured');
260
+ if (!cfg.allow_claim || !cfg.allow_values.length)
261
+ throw new OidcConfigError('Native OIDC login requires webui_oidc.allow_claim and allow_values');
262
+ if (cfg.profile_map_error)
263
+ throw new OidcConfigError(cfg.profile_map_error);
264
+ return cfg;
265
+ }
266
+ /** Configured `redirect_uri` origin, when set and valid (Python `_configured_oidc_origin`). */
267
+ configuredOrigin() {
268
+ const redirect = str(this.lastConfig?.redirect_uri).trim();
269
+ if (!redirect)
270
+ return null;
271
+ try {
272
+ const u = new URL(redirect);
273
+ return ['http:', 'https:'].includes(u.protocol) && u.host ? `${u.protocol}//${u.host.toLowerCase()}` : null;
274
+ }
275
+ catch {
276
+ return null;
277
+ }
278
+ }
279
+ redirectUri(cfg, requestBaseUrl) {
280
+ return cfg.redirect_uri || requestBaseUrl.replace(/\/+$/, '') + '/api/auth/oidc/callback';
281
+ }
282
+ prune() {
283
+ const now = this.deps.now();
284
+ for (const [k, v] of this.pending)
285
+ if (now - v.created_at > PENDING_TTL_S)
286
+ this.pending.delete(k);
287
+ for (const [k, v] of this.nativeFlows)
288
+ if (now - v.created_at > NATIVE_FLOW_TTL_S)
289
+ this.nativeFlows.delete(k);
290
+ for (const [k, v] of this.exchanges)
291
+ if (now - v.created_at > NATIVE_EXCHANGE_TTL_S)
292
+ this.exchanges.delete(k);
293
+ }
294
+ trim(map, max) {
295
+ const overflow = map.size - max + 1;
296
+ if (overflow <= 0)
297
+ return;
298
+ for (const [k] of [...map.entries()].sort((a, b) => a[1].created_at - b[1].created_at).slice(0, overflow))
299
+ map.delete(k);
300
+ }
301
+ /** Python `build_authorization_redirect`. */
302
+ async authorizationRedirect(requestBaseUrl, nextPath, nativeFlowId) {
303
+ const cfg = await this.require();
304
+ const discovery = await this.discoveryDocument(cfg);
305
+ const endpoint = str(discovery.authorization_endpoint).trim();
306
+ if (!endpoint)
307
+ throw new OidcConfigError('OIDC discovery document is missing authorization_endpoint');
308
+ const state = randomBytes(24).toString('base64url');
309
+ const nonce = randomBytes(24).toString('base64url');
310
+ const verifier = randomBytes(48).toString('base64url');
311
+ const challenge = b64u(createHash('sha256').update(verifier, 'ascii').digest());
312
+ this.prune();
313
+ if (nativeFlowId) {
314
+ const flow = this.nativeFlows.get(nativeFlowId);
315
+ if (!flow)
316
+ throw new OidcAuthError('Invalid or expired native OIDC flow', 401);
317
+ if (!safeEq(normalizeServerOrigin(requestBaseUrl), flow.server_origin))
318
+ throw new OidcAuthError('Native OIDC flow belongs to a different server', 401);
319
+ }
320
+ this.trim(this.pending, MAX_PENDING);
321
+ this.pending.set(state, { created_at: this.deps.now(), nonce, code_verifier: verifier, next_path: safeNextPath(nextPath), native_flow_id: nativeFlowId });
322
+ const params = new URLSearchParams({ response_type: 'code', client_id: cfg.client_id, redirect_uri: this.redirectUri(cfg, requestBaseUrl), scope: cfg.scopes.join(' '), state, nonce, code_challenge: challenge, code_challenge_method: 'S256' });
323
+ return `${endpoint}?${params.toString()}`;
324
+ }
325
+ consumeFailedProviderAuthorization(state) {
326
+ this.prune();
327
+ const pending = this.pending.get(state);
328
+ this.pending.delete(state);
329
+ return pending?.native_flow_id ?? null;
330
+ }
331
+ /** Python `complete_authorization_code_flow`. */
332
+ async completeCodeFlow(requestBaseUrl, state, code) {
333
+ const cfg = await this.require();
334
+ this.prune();
335
+ const pending = this.pending.get(state);
336
+ this.pending.delete(state);
337
+ if (!pending)
338
+ throw new OidcAuthError('Invalid OIDC state', 401);
339
+ try {
340
+ const discovery = await this.discoveryDocument(cfg);
341
+ const discoveryIssuer = str(discovery.issuer).trim();
342
+ if (discoveryIssuer && discoveryIssuer !== cfg.issuer)
343
+ throw new OidcAuthError('OIDC discovery issuer did not match the configured issuer', 502);
344
+ const tokenEndpoint = str(discovery.token_endpoint).trim();
345
+ if (!tokenEndpoint)
346
+ throw new OidcConfigError('OIDC discovery document is missing token_endpoint');
347
+ const form = { grant_type: 'authorization_code', client_id: cfg.client_id, code, code_verifier: pending.code_verifier, redirect_uri: this.redirectUri(cfg, requestBaseUrl) };
348
+ if (cfg.client_secret)
349
+ form.client_secret = cfg.client_secret;
350
+ const token = await this.postForm(cfg, tokenEndpoint, form);
351
+ const idToken = str(token.id_token).trim();
352
+ if (!idToken)
353
+ throw new OidcAuthError('OIDC token response did not include an id_token', 502);
354
+ const claims = await this.validateIdToken(cfg, idToken, pending.nonce, str(discovery.jwks_uri).trim());
355
+ this.enforceAllowlist(claims, cfg);
356
+ const boundProfile = this.resolveBoundProfile(cfg, claims);
357
+ const binding = this.binding(cfg, boundProfile, this.ownerPermission(cfg, claims));
358
+ return { next_path: pending.next_path, native_flow_id: pending.native_flow_id, subject: str(claims.sub), email: str(claims.email), bound_profile: boundProfile, oidc_binding: binding, claims };
359
+ }
360
+ catch (error) {
361
+ if (error instanceof OidcAuthError || error instanceof OidcConfigError)
362
+ error.nativeFlowId = pending.native_flow_id;
363
+ throw error;
364
+ }
365
+ }
366
+ /** Python `begin_native_authorization`. */
367
+ async beginNative(requestBaseUrl, callbackUrl, clientState, codeChallenge) {
368
+ if (!(await this.enabled()))
369
+ throw new OidcConfigError('Native OIDC login is not configured');
370
+ const origin = normalizeServerOrigin(requestBaseUrl);
371
+ const callback = validateNativeCallback(callbackUrl);
372
+ const state = str(clientState).trim();
373
+ const challenge = str(codeChallenge).trim();
374
+ if (!NATIVE_VALUE_RE.test(state))
375
+ throw new OidcAuthError('Invalid native OIDC state', 400);
376
+ if (!PKCE_CHALLENGE_RE.test(challenge))
377
+ throw new OidcAuthError('Invalid native OIDC PKCE challenge', 400);
378
+ this.prune();
379
+ if (this.nativeFlows.size >= MAX_PENDING)
380
+ throw new OidcAuthError('Too many pending native OIDC flows', 429);
381
+ const flowId = randomBytes(24).toString('base64url');
382
+ const serverId = serverIdentity(origin);
383
+ this.nativeFlows.set(flowId, { created_at: this.deps.now(), callback_url: callback, client_state: state, code_challenge: challenge, server_origin: origin, server_id: serverId });
384
+ return { flow_id: flowId, authorization_url: `${this.nativeAuthorizationBase(origin)}/api/auth/oidc/start?${new URLSearchParams({ native_flow: flowId }).toString()}`, server_id: serverId, expires_in: NATIVE_FLOW_TTL_S };
385
+ }
386
+ nativeAuthorizationBase(origin) {
387
+ const redirect = str(this.lastConfig?.redirect_uri).trim();
388
+ if (!redirect)
389
+ return origin;
390
+ let u;
391
+ try {
392
+ u = new URL(redirect);
393
+ }
394
+ catch {
395
+ return origin;
396
+ }
397
+ const callbackPath = '/api/auth/oidc/callback';
398
+ if (u.search || u.hash || !u.pathname.endsWith(callbackPath))
399
+ return origin;
400
+ let redirectOrigin;
401
+ try {
402
+ redirectOrigin = normalizeServerOrigin(`${u.protocol}//${u.host}`);
403
+ }
404
+ catch {
405
+ return origin;
406
+ }
407
+ if (!safeEq(redirectOrigin, origin))
408
+ return origin;
409
+ const prefix = u.pathname.slice(0, -callbackPath.length).replace(/\/+$/, '');
410
+ let decoded;
411
+ try {
412
+ decoded = decodeURIComponent(prefix);
413
+ }
414
+ catch {
415
+ return origin;
416
+ }
417
+ if (!prefix || decoded.includes('\\') || decoded.split('/').some((s) => s === '.' || s === '..') || /[\x00-\x1f\x7f\s]/.test(decoded))
418
+ return origin;
419
+ return origin + prefix;
420
+ }
421
+ callbackWith(flow, params) {
422
+ const sep = flow.callback_url.includes('?') ? '&' : '?';
423
+ return flow.callback_url + sep + new URLSearchParams(params).toString();
424
+ }
425
+ /** Python `finish_native_authorization`: mint one short-lived exchange code. */
426
+ finishNative(requestBaseUrl, flowId, identity) {
427
+ this.prune();
428
+ const flow = this.nativeFlows.get(flowId);
429
+ this.nativeFlows.delete(flowId);
430
+ if (!flow)
431
+ throw new OidcAuthError('Invalid or expired native OIDC flow', 401);
432
+ if (!safeEq(normalizeServerOrigin(requestBaseUrl), flow.server_origin))
433
+ throw new OidcAuthError('Native OIDC flow belongs to a different server', 401);
434
+ this.trim(this.exchanges, MAX_PENDING);
435
+ const code = randomBytes(32).toString('base64url');
436
+ this.exchanges.set(code, { created_at: this.deps.now(), flow_id: flowId, client_state: flow.client_state, code_challenge: flow.code_challenge, server_origin: flow.server_origin, subject: identity.subject, email: identity.email, bound_profile: identity.bound_profile, oidc_binding: identity.oidc_binding });
437
+ return this.callbackWith(flow, { code, state: flow.client_state, flow_id: flowId, server_id: flow.server_id });
438
+ }
439
+ failNative(requestBaseUrl, flowId, error) {
440
+ this.prune();
441
+ const flow = this.nativeFlows.get(flowId);
442
+ this.nativeFlows.delete(flowId);
443
+ if (!flow)
444
+ throw new OidcAuthError('Invalid or expired native OIDC flow', 401);
445
+ if (!safeEq(normalizeServerOrigin(requestBaseUrl), flow.server_origin))
446
+ throw new OidcAuthError('Native OIDC flow belongs to a different server', 401);
447
+ return this.callbackWith(flow, { error: error || 'authentication_failed', state: flow.client_state, flow_id: flowId, server_id: flow.server_id });
448
+ }
449
+ /** Python `exchange_native_authorization`. */
450
+ async exchangeNative(requestBaseUrl, flowId, code, clientState, verifier) {
451
+ this.prune();
452
+ const exchange = this.exchanges.get(code);
453
+ this.exchanges.delete(code);
454
+ if (!exchange)
455
+ throw new OidcAuthError('Invalid or expired native OIDC exchange code', 401);
456
+ if (!safeEq(normalizeServerOrigin(requestBaseUrl), exchange.server_origin))
457
+ throw new OidcAuthError('Native OIDC exchange code belongs to a different server', 401);
458
+ if (!safeEq(flowId, exchange.flow_id))
459
+ throw new OidcAuthError('Native OIDC flow did not match', 401);
460
+ if (!safeEq(clientState, exchange.client_state))
461
+ throw new OidcAuthError('Native OIDC state did not match', 401);
462
+ if (!PKCE_VERIFIER_RE.test(verifier))
463
+ throw new OidcAuthError('Native OIDC PKCE verifier did not match', 401);
464
+ if (!safeEq(b64u(createHash('sha256').update(verifier, 'ascii').digest()), exchange.code_challenge))
465
+ throw new OidcAuthError('Native OIDC PKCE verifier did not match', 401);
466
+ if (!(await this.bindingIsCurrent(exchange.oidc_binding, exchange.bound_profile)))
467
+ throw new OidcAuthError('OIDC policy changed; sign in again', 401);
468
+ const result = { subject: exchange.subject, email: exchange.email, bound_profile: exchange.bound_profile };
469
+ if (exchange.oidc_binding)
470
+ result.oidc_binding = exchange.oidc_binding;
471
+ return result;
472
+ }
473
+ cancelNative(flowId, clientState) {
474
+ if (!NATIVE_VALUE_RE.test(flowId) || !NATIVE_VALUE_RE.test(clientState))
475
+ return false;
476
+ const flow = this.nativeFlows.get(flowId);
477
+ if (flow && !safeEq(clientState, flow.client_state))
478
+ return false;
479
+ const matching = [...this.exchanges.entries()].filter(([, e]) => safeEq(e.flow_id, flowId));
480
+ if (matching.some(([, e]) => !safeEq(clientState, e.client_state)))
481
+ return false;
482
+ let removed = this.nativeFlows.delete(flowId);
483
+ for (const [code] of matching) {
484
+ this.exchanges.delete(code);
485
+ removed = true;
486
+ }
487
+ for (const [state, p] of this.pending)
488
+ if (p.native_flow_id && safeEq(p.native_flow_id, flowId)) {
489
+ this.pending.delete(state);
490
+ removed = true;
491
+ }
492
+ return removed;
493
+ }
494
+ // ── policy ───────────────────────────────────────────────────────────
495
+ enforceAllowlist(claims, cfg) {
496
+ if (!cfg.allow_claim)
497
+ return;
498
+ const value = claimPath(claims, cfg.allow_claim);
499
+ if (value === undefined || value === null)
500
+ throw new OidcAuthError('OIDC identity is not allowed', 403);
501
+ const actual = claimValues(value);
502
+ if (cfg.allow_values.length) {
503
+ if (!cfg.allow_values.some((v) => actual.has(v)))
504
+ throw new OidcAuthError('OIDC identity is not allowed', 403);
505
+ return;
506
+ }
507
+ if (!actual.size)
508
+ throw new OidcAuthError('OIDC identity is not allowed', 403);
509
+ }
510
+ ownerPermission(cfg, claims) {
511
+ if (!cfg.owner_policy_configured || !cfg.owner_values.length || !cfg.owner_claim)
512
+ return false;
513
+ const value = claimPath(claims, cfg.owner_claim);
514
+ const present = typeof value === 'string' ? [value] : Array.isArray(value) && value.every((v) => typeof v === 'string') ? value : null;
515
+ return present?.some((v) => cfg.owner_values.includes(v)) ?? false;
516
+ }
517
+ resolveBoundProfile(cfg, claims) {
518
+ if (!cfg.profile_map_configured)
519
+ return null;
520
+ const value = claimPath(claims, cfg.profile_claim || 'sub');
521
+ if (isDict(value) || Array.isArray(value))
522
+ throw new OidcAuthError('OIDC identity is not assigned to a profile', 403);
523
+ const profile = cfg.profile_map?.[str(value).trim()];
524
+ if (!profile)
525
+ throw new OidcAuthError('OIDC identity is not assigned to a profile', 403);
526
+ if (profile !== 'default' && !/^[a-z0-9][a-z0-9_-]{0,63}$/.test(profile))
527
+ throw new OidcConfigError(`OIDC profile mapping targets invalid profile '${profile}'`);
528
+ const home = this.deps.profileHome(profile);
529
+ if (!existsSync(home) || !statSync(home).isDirectory())
530
+ throw new OidcConfigError(`OIDC profile mapping target '${profile}' does not exist`);
531
+ return profile;
532
+ }
533
+ /** Python `_oidc_profile_binding`: fingerprint of every policy input plus the profile identity (`st_dev:st_ino`). */
534
+ binding(cfg, profile, owner = false) {
535
+ const payload = {
536
+ allow_claim: cfg.allow_claim, allow_values: [...cfg.allow_values].map(String).sort(), client_id: cfg.client_id, issuer: cfg.issuer, owner_claim: cfg.owner_claim, owner_policy_configured: cfg.owner_policy_configured,
537
+ owner_values: [...cfg.owner_values].map(String).sort(), profile_claim: cfg.profile_claim || 'sub', profile_map: cfg.profile_map ?? {}, profile_map_configured: cfg.profile_map_configured,
538
+ };
539
+ const fingerprint = createHash('sha256').update(canonicalJson(payload), 'utf8').digest('hex');
540
+ let identity = '';
541
+ if (profile) {
542
+ const st = statSync(this.deps.profileHome(profile), { bigint: true });
543
+ identity = `${String(st.dev)}:${String(st.ino)}`;
544
+ }
545
+ const out = { mapping_fingerprint: fingerprint, profile_identity: identity };
546
+ if (owner)
547
+ out.owner = true;
548
+ return out;
549
+ }
550
+ async bindingIsCurrent(binding, profile, cfg) {
551
+ if (!binding)
552
+ return true;
553
+ try {
554
+ const resolved = cfg ?? (await this.require());
555
+ const expected = this.binding(resolved, str(profile).trim() || null);
556
+ return safeEq(str(binding.mapping_fingerprint), str(expected.mapping_fingerprint)) && safeEq(str(binding.profile_identity), str(expected.profile_identity));
557
+ }
558
+ catch {
559
+ return false;
560
+ }
561
+ }
562
+ /** Python `oidc_session_binding_is_current`. */
563
+ async sessionBindingIsCurrent(info, cfg) {
564
+ const profile = str(info.bound_profile).trim();
565
+ const fingerprint = str(info.oidc_mapping_fingerprint);
566
+ if (!fingerprint && !profile && !info.oidc_owner)
567
+ return true;
568
+ return this.bindingIsCurrent({ mapping_fingerprint: fingerprint, profile_identity: info.oidc_profile_identity ?? '' }, profile, cfg);
569
+ }
570
+ /** Python `oidc_session_can_manage_server`. */
571
+ async sessionCanManageServer(info) {
572
+ let cfg;
573
+ try {
574
+ cfg = await this.require();
575
+ }
576
+ catch {
577
+ return false;
578
+ }
579
+ if (cfg.config_read_failed)
580
+ return false;
581
+ if (!cfg.owner_policy_configured)
582
+ return str(info.bound_profile).trim() ? false : this.sessionBindingIsCurrent(info, cfg);
583
+ if (!info.oidc_owner)
584
+ return false;
585
+ return this.sessionBindingIsCurrent(info, cfg);
586
+ }
587
+ /** Python `oidc_owner_policy_is_configured` (fails closed on an unreadable config). */
588
+ async ownerPolicyConfigured() {
589
+ try {
590
+ const cfg = await this.resolve();
591
+ return cfg.owner_policy_configured || cfg.config_read_failed;
592
+ }
593
+ catch {
594
+ return true;
595
+ }
596
+ }
597
+ // ── discovery, JWKS, tokens ──────────────────────────────────────────
598
+ /** The vetted addresses to pin the request to, or null for an operator-trusted private host (plain fetch). */
599
+ async validateOutbound(cfg, url) {
600
+ let u;
601
+ try {
602
+ u = new URL(url);
603
+ }
604
+ catch {
605
+ throw new OidcAuthError('OIDC endpoint URLs must use https', 502);
606
+ }
607
+ if (u.protocol !== 'https:')
608
+ throw new OidcAuthError('OIDC endpoint URLs must use https', 502);
609
+ if (u.username || u.password)
610
+ throw new OidcAuthError('OIDC endpoint URLs must not contain credentials', 502);
611
+ const hostname = u.hostname.replace(/^\[|\]$/g, '');
612
+ if (!hostname)
613
+ throw new OidcAuthError('OIDC endpoint URL was missing a hostname', 502);
614
+ const normalized = hostname.toLowerCase().replace(/\.+$/, '');
615
+ if (cfg.trusted_private_hosts.includes(normalized))
616
+ return null;
617
+ try {
618
+ return await vettedAddresses(hostname, disallowedIp, this.deps.pinned().lookup);
619
+ }
620
+ catch (error) {
621
+ if (error instanceof BlockedAddressError)
622
+ throw new OidcAuthError('OIDC endpoint URLs must not target private or local addresses', 502);
623
+ throw new OidcAuthError(`Failed to resolve OIDC endpoint host: ${hostname}`, 502);
624
+ }
625
+ }
626
+ async fetchJson(cfg, url, init, failure) {
627
+ const addresses = await this.validateOutbound(cfg, url);
628
+ let res;
629
+ try {
630
+ const signal = AbortSignal.timeout(10_000);
631
+ res = addresses ? await this.deps.pinned().fetch(url, { ...init, signal }, addresses) : await this.deps.fetch()(url, { ...init, redirect: 'error', signal });
632
+ }
633
+ catch {
634
+ throw new OidcAuthError(failure, 502);
635
+ }
636
+ if (!res.ok)
637
+ throw new OidcAuthError(failure, 502);
638
+ let text;
639
+ try {
640
+ const raw = await readCapped(res, 1024 * 1024);
641
+ if (!raw)
642
+ throw new Error('too large');
643
+ text = raw.toString('utf8');
644
+ }
645
+ catch {
646
+ throw new OidcAuthError(failure, 502);
647
+ }
648
+ if (/\b(NaN|Infinity|-Infinity)\b/.test(text.replace(/"(?:[^"\\]|\\.)*"/g, '')))
649
+ throw new OidcAuthError(`OIDC endpoint returned invalid JSON: ${url}`, 502);
650
+ let payload;
651
+ try {
652
+ payload = JSON.parse(text);
653
+ }
654
+ catch {
655
+ throw new OidcAuthError(`OIDC endpoint returned invalid JSON: ${url}`, 502);
656
+ }
657
+ return isDict(payload) ? payload : {};
658
+ }
659
+ async discoveryDocument(cfg) {
660
+ const url = cfg.issuer.endsWith('/.well-known/openid-configuration') ? cfg.issuer : cfg.issuer.replace(/\/+$/, '') + '/.well-known/openid-configuration';
661
+ const hit = this.discovery.get(url);
662
+ if (hit && hit.until > this.deps.now())
663
+ return structuredClone(hit.value);
664
+ const data = await this.fetchJson(cfg, url, { headers: { Accept: 'application/json' } }, `Failed to reach OIDC endpoint: ${url}`);
665
+ if (!Object.keys(data).length)
666
+ throw new OidcAuthError('OIDC discovery response was not a JSON object', 502);
667
+ this.discovery.set(url, { until: this.deps.now() + CACHE_TTL_S, value: structuredClone(data) });
668
+ return data;
669
+ }
670
+ async jwksDocument(cfg, uri, force = false) {
671
+ if (!uri)
672
+ throw new OidcConfigError('OIDC discovery document is missing jwks_uri');
673
+ if (force)
674
+ this.jwks.delete(uri);
675
+ else {
676
+ const hit = this.jwks.get(uri);
677
+ if (hit && hit.until > this.deps.now())
678
+ return structuredClone(hit.value);
679
+ }
680
+ const data = await this.fetchJson(cfg, uri, { headers: { Accept: 'application/json' } }, `Failed to reach OIDC endpoint: ${uri}`);
681
+ this.jwks.set(uri, { until: this.deps.now() + CACHE_TTL_S, value: structuredClone(data) });
682
+ return data;
683
+ }
684
+ postForm(cfg, url, form) {
685
+ return this.fetchJson(cfg, url, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(form).toString() }, 'Failed to exchange the OIDC authorization code');
686
+ }
687
+ async validateIdToken(cfg, token, nonce, jwksUri) {
688
+ const parts = token.split('.');
689
+ if (parts.length !== 3)
690
+ throw new OidcAuthError('OIDC id_token was not a JWT');
691
+ const [h, p, s] = parts;
692
+ let header;
693
+ let claims;
694
+ let signature;
695
+ try {
696
+ header = JSON.parse(b64uDecode(h).toString('utf8'));
697
+ claims = JSON.parse(b64uDecode(p).toString('utf8'));
698
+ signature = b64uDecode(s);
699
+ }
700
+ catch {
701
+ throw new OidcAuthError('OIDC id_token could not be decoded');
702
+ }
703
+ if (!isDict(header) || !isDict(claims))
704
+ throw new OidcAuthError('OIDC id_token payload was malformed');
705
+ const alg = str(header.alg).trim();
706
+ if (!alg || alg === 'none')
707
+ throw new OidcAuthError('OIDC id_token uses an unsupported signing algorithm');
708
+ let jwks = await this.jwksDocument(cfg, jwksUri);
709
+ let key;
710
+ try {
711
+ key = selectKey(jwks, header, alg);
712
+ }
713
+ catch (error) {
714
+ if (!(error instanceof OidcAuthError && error.message.includes('did not contain the signing key')))
715
+ throw error;
716
+ jwks = await this.jwksDocument(cfg, jwksUri, true);
717
+ key = selectKey(jwks, header, alg);
718
+ }
719
+ verifyJwt(key, alg, Buffer.from(`${h}.${p}`, 'ascii'), signature);
720
+ this.validateClaims(claims, cfg, nonce);
721
+ if (!str(claims.sub).trim())
722
+ throw new OidcAuthError('OIDC id_token did not include a subject');
723
+ return claims;
724
+ }
725
+ validateClaims(claims, cfg, nonce) {
726
+ const now = this.deps.now();
727
+ if (str(claims.iss).trim() !== cfg.issuer)
728
+ throw new OidcAuthError('OIDC id_token issuer did not match the configured issuer');
729
+ const aud = claims.aud;
730
+ const audiences = Array.isArray(aud) ? aud.map((a) => str(a)) : aud === null || aud === undefined ? [] : [str(aud)];
731
+ if (!audiences.includes(cfg.client_id))
732
+ throw new OidcAuthError('OIDC id_token audience did not include this client');
733
+ if (audiences.length > 1 && !['', cfg.client_id].includes(str(claims.azp).trim()))
734
+ throw new OidcAuthError('OIDC id_token azp did not match this client');
735
+ const num = (name) => {
736
+ const v = claims[name];
737
+ if (v === null || v === undefined)
738
+ return null;
739
+ const n = typeof v === 'number' ? v : Number(str(v));
740
+ if (!Number.isFinite(n))
741
+ throw new OidcAuthError(`OIDC id_token claim ${name} was not numeric`);
742
+ return n;
743
+ };
744
+ const exp = num('exp');
745
+ if (exp === null || exp < now - CLOCK_SKEW_S)
746
+ throw new OidcAuthError('OIDC id_token has expired');
747
+ const nbf = num('nbf');
748
+ if (nbf !== null && nbf > now + CLOCK_SKEW_S)
749
+ throw new OidcAuthError('OIDC id_token is not valid yet');
750
+ const iat = num('iat');
751
+ if (iat !== null && iat > now + CLOCK_SKEW_S)
752
+ throw new OidcAuthError('OIDC id_token has an invalid issued-at time');
753
+ if (str(claims.nonce).trim() !== nonce)
754
+ throw new OidcAuthError('OIDC id_token nonce did not match the login request');
755
+ }
756
+ }
757
+ /**
758
+ * Python `json.dumps(value, sort_keys=True, separators=(",", ":"))` — including its default `ensure_ascii=True`, which
759
+ * escapes every non-ASCII character as `\uXXXX`; the mapping fingerprint persisted by the Python server must verify here.
760
+ */
761
+ export function canonicalJson(value) {
762
+ if (Array.isArray(value))
763
+ return `[${value.map(canonicalJson).join(',')}]`;
764
+ if (isDict(value))
765
+ return `{${Object.keys(value).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).map((k) => `${pyJsonString(k)}:${canonicalJson(value[k])}`).join(',')}}`;
766
+ if (typeof value === 'string')
767
+ return pyJsonString(value);
768
+ return JSON.stringify(value);
769
+ }
770
+ /** `json.dumps` of one string with `ensure_ascii=True` (UTF-16 code units above 0x7f become `\uXXXX`). */
771
+ function pyJsonString(text) {
772
+ return JSON.stringify(text).replaceAll(/[\u007f-\uffff]/g, (ch) => `\\u${ch.charCodeAt(0).toString(16).padStart(4, '0')}`);
773
+ }
774
+ const EC_CURVES = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' };
775
+ function selectKey(jwks, header, alg) {
776
+ const keys = Array.isArray(jwks.keys) ? jwks.keys.filter(isDict) : [];
777
+ if (!keys.length)
778
+ throw new OidcAuthError('OIDC JWKS did not contain any signing keys', 502);
779
+ const kid = str(header.kid).trim();
780
+ const match = keys.find((k) => {
781
+ if (k.use !== undefined && k.use !== null && k.use !== 'sig')
782
+ return false;
783
+ if (kid && str(k.kid).trim() !== kid)
784
+ return false;
785
+ if (k.alg !== undefined && k.alg !== null && k.alg !== alg)
786
+ return false;
787
+ const kty = str(k.kty).trim();
788
+ if (alg.startsWith('RS'))
789
+ return kty === 'RSA';
790
+ if (alg.startsWith('ES'))
791
+ return kty === 'EC' && str(k.crv).trim() === EC_CURVES[alg];
792
+ return true;
793
+ });
794
+ if (!match)
795
+ throw new OidcAuthError('OIDC JWKS did not contain the signing key for this id_token', 502);
796
+ const kty = str(match.kty).trim();
797
+ try {
798
+ if (kty === 'RSA') {
799
+ if (!match.n || !match.e)
800
+ throw new Error('missing');
801
+ return createPublicKey({ key: { kty: 'RSA', n: str(match.n), e: str(match.e) }, format: 'jwk' });
802
+ }
803
+ if (kty === 'EC') {
804
+ const crv = str(match.crv).trim();
805
+ if (!['P-256', 'P-384', 'P-521'].includes(crv))
806
+ throw new OidcAuthError(`Unsupported OIDC EC curve: ${crv}`, 502);
807
+ if (!match.x || !match.y)
808
+ throw new Error('missing');
809
+ return createPublicKey({ key: { kty: 'EC', crv, x: str(match.x), y: str(match.y) }, format: 'jwk' });
810
+ }
811
+ }
812
+ catch (error) {
813
+ if (error instanceof OidcAuthError)
814
+ throw error;
815
+ throw new OidcAuthError('OIDC JWKS key was missing a required parameter', 502);
816
+ }
817
+ throw new OidcAuthError(`Unsupported OIDC key type: ${kty}`, 502);
818
+ }
819
+ function verifyJwt(key, alg, signed, signature) {
820
+ const hash = { RS256: 'sha256', RS384: 'sha384', RS512: 'sha512', ES256: 'sha256', ES384: 'sha384', ES512: 'sha512' }[alg];
821
+ if (!hash)
822
+ throw new OidcAuthError(`Unsupported OIDC signing algorithm: ${alg}`, 502);
823
+ const partSize = { ES256: 32, ES384: 48, ES512: 66 }[alg];
824
+ if (partSize !== undefined && signature.length !== partSize * 2)
825
+ throw new OidcAuthError('OIDC id_token ECDSA signature was malformed');
826
+ let ok = false;
827
+ try {
828
+ ok = cryptoVerify(hash, signed, alg.startsWith('ES') ? { key, dsaEncoding: 'ieee-p1363' } : key, signature);
829
+ }
830
+ catch {
831
+ ok = false;
832
+ }
833
+ if (!ok)
834
+ throw new OidcAuthError('OIDC id_token signature verification failed');
835
+ }
836
+ //# sourceMappingURL=oidc.js.map