@antasphere/chassis-server 1.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 (798) hide show
  1. package/LICENSE +82 -0
  2. package/dist/accounts/deletion.d.ts +163 -0
  3. package/dist/accounts/deletion.d.ts.map +1 -0
  4. package/dist/accounts/deletion.js +360 -0
  5. package/dist/accounts/deletion.js.map +1 -0
  6. package/dist/accounts/erasure-log.d.ts +66 -0
  7. package/dist/accounts/erasure-log.d.ts.map +1 -0
  8. package/dist/accounts/erasure-log.js +117 -0
  9. package/dist/accounts/erasure-log.js.map +1 -0
  10. package/dist/accounts/index.d.ts +6 -0
  11. package/dist/accounts/index.d.ts.map +1 -0
  12. package/dist/accounts/index.js +6 -0
  13. package/dist/accounts/index.js.map +1 -0
  14. package/dist/accounts/mint-refusal.d.ts +47 -0
  15. package/dist/accounts/mint-refusal.d.ts.map +1 -0
  16. package/dist/accounts/mint-refusal.js +59 -0
  17. package/dist/accounts/mint-refusal.js.map +1 -0
  18. package/dist/accounts/signup-duplicate.d.ts +14 -0
  19. package/dist/accounts/signup-duplicate.d.ts.map +1 -0
  20. package/dist/accounts/signup-duplicate.js +25 -0
  21. package/dist/accounts/signup-duplicate.js.map +1 -0
  22. package/dist/accounts/superadmin.d.ts +27 -0
  23. package/dist/accounts/superadmin.d.ts.map +1 -0
  24. package/dist/accounts/superadmin.js +46 -0
  25. package/dist/accounts/superadmin.js.map +1 -0
  26. package/dist/api/apikeys.d.ts +14 -0
  27. package/dist/api/apikeys.d.ts.map +1 -0
  28. package/dist/api/apikeys.js +124 -0
  29. package/dist/api/apikeys.js.map +1 -0
  30. package/dist/api/audit.d.ts +4 -0
  31. package/dist/api/audit.d.ts.map +1 -0
  32. package/dist/api/audit.js +75 -0
  33. package/dist/api/audit.js.map +1 -0
  34. package/dist/api/break-glass.d.ts +48 -0
  35. package/dist/api/break-glass.d.ts.map +1 -0
  36. package/dist/api/break-glass.js +217 -0
  37. package/dist/api/break-glass.js.map +1 -0
  38. package/dist/api/cli-auth.d.ts +84 -0
  39. package/dist/api/cli-auth.d.ts.map +1 -0
  40. package/dist/api/cli-auth.js +177 -0
  41. package/dist/api/cli-auth.js.map +1 -0
  42. package/dist/api/create-api.d.ts +123 -0
  43. package/dist/api/create-api.d.ts.map +1 -0
  44. package/dist/api/create-api.js +1165 -0
  45. package/dist/api/create-api.js.map +1 -0
  46. package/dist/api/demo-passes.d.ts +45 -0
  47. package/dist/api/demo-passes.d.ts.map +1 -0
  48. package/dist/api/demo-passes.js +143 -0
  49. package/dist/api/demo-passes.js.map +1 -0
  50. package/dist/api/errors.d.ts +5 -0
  51. package/dist/api/errors.d.ts.map +1 -0
  52. package/dist/api/errors.js +5 -0
  53. package/dist/api/errors.js.map +1 -0
  54. package/dist/api/export.d.ts +63 -0
  55. package/dist/api/export.d.ts.map +1 -0
  56. package/dist/api/export.js +393 -0
  57. package/dist/api/export.js.map +1 -0
  58. package/dist/api/files.d.ts +40 -0
  59. package/dist/api/files.d.ts.map +1 -0
  60. package/dist/api/files.js +150 -0
  61. package/dist/api/files.js.map +1 -0
  62. package/dist/api/index.d.ts +17 -0
  63. package/dist/api/index.d.ts.map +1 -0
  64. package/dist/api/index.js +17 -0
  65. package/dist/api/index.js.map +1 -0
  66. package/dist/api/invitations.d.ts +50 -0
  67. package/dist/api/invitations.d.ts.map +1 -0
  68. package/dist/api/invitations.js +313 -0
  69. package/dist/api/invitations.js.map +1 -0
  70. package/dist/api/members.d.ts +25 -0
  71. package/dist/api/members.d.ts.map +1 -0
  72. package/dist/api/members.js +522 -0
  73. package/dist/api/members.js.map +1 -0
  74. package/dist/api/onboarding.d.ts +26 -0
  75. package/dist/api/onboarding.d.ts.map +1 -0
  76. package/dist/api/onboarding.js +23 -0
  77. package/dist/api/onboarding.js.map +1 -0
  78. package/dist/api/openapi-doc.d.ts +21 -0
  79. package/dist/api/openapi-doc.d.ts.map +1 -0
  80. package/dist/api/openapi-doc.js +25 -0
  81. package/dist/api/openapi-doc.js.map +1 -0
  82. package/dist/api/projects.d.ts +24 -0
  83. package/dist/api/projects.d.ts.map +1 -0
  84. package/dist/api/projects.js +624 -0
  85. package/dist/api/projects.js.map +1 -0
  86. package/dist/api/scope-routes.d.ts +12 -0
  87. package/dist/api/scope-routes.d.ts.map +1 -0
  88. package/dist/api/scope-routes.js +2 -0
  89. package/dist/api/scope-routes.js.map +1 -0
  90. package/dist/api/sso-connect.d.ts +70 -0
  91. package/dist/api/sso-connect.d.ts.map +1 -0
  92. package/dist/api/sso-connect.js +164 -0
  93. package/dist/api/sso-connect.js.map +1 -0
  94. package/dist/api/sso-logout.d.ts +41 -0
  95. package/dist/api/sso-logout.d.ts.map +1 -0
  96. package/dist/api/sso-logout.js +34 -0
  97. package/dist/api/sso-logout.js.map +1 -0
  98. package/dist/api/teams.d.ts +43 -0
  99. package/dist/api/teams.d.ts.map +1 -0
  100. package/dist/api/teams.js +447 -0
  101. package/dist/api/teams.js.map +1 -0
  102. package/dist/api/workspaces.d.ts +114 -0
  103. package/dist/api/workspaces.d.ts.map +1 -0
  104. package/dist/api/workspaces.js +462 -0
  105. package/dist/api/workspaces.js.map +1 -0
  106. package/dist/apikeys/index.d.ts +3 -0
  107. package/dist/apikeys/index.d.ts.map +1 -0
  108. package/dist/apikeys/index.js +3 -0
  109. package/dist/apikeys/index.js.map +1 -0
  110. package/dist/apikeys/peppers.d.ts +53 -0
  111. package/dist/apikeys/peppers.d.ts.map +1 -0
  112. package/dist/apikeys/peppers.js +97 -0
  113. package/dist/apikeys/peppers.js.map +1 -0
  114. package/dist/apikeys/service.d.ts +56 -0
  115. package/dist/apikeys/service.d.ts.map +1 -0
  116. package/dist/apikeys/service.js +196 -0
  117. package/dist/apikeys/service.js.map +1 -0
  118. package/dist/app.d.ts +65 -0
  119. package/dist/app.d.ts.map +1 -0
  120. package/dist/app.js +142 -0
  121. package/dist/app.js.map +1 -0
  122. package/dist/audit/filters.d.ts +38 -0
  123. package/dist/audit/filters.d.ts.map +1 -0
  124. package/dist/audit/filters.js +97 -0
  125. package/dist/audit/filters.js.map +1 -0
  126. package/dist/audit/index.d.ts +3 -0
  127. package/dist/audit/index.d.ts.map +1 -0
  128. package/dist/audit/index.js +3 -0
  129. package/dist/audit/index.js.map +1 -0
  130. package/dist/audit/service.d.ts +65 -0
  131. package/dist/audit/service.d.ts.map +1 -0
  132. package/dist/audit/service.js +103 -0
  133. package/dist/audit/service.js.map +1 -0
  134. package/dist/boot.d.ts +8 -0
  135. package/dist/boot.d.ts.map +1 -0
  136. package/dist/boot.js +822 -0
  137. package/dist/boot.js.map +1 -0
  138. package/dist/constant-time.d.ts +3 -0
  139. package/dist/constant-time.d.ts.map +1 -0
  140. package/dist/constant-time.js +10 -0
  141. package/dist/constant-time.js.map +1 -0
  142. package/dist/email/driver.d.ts +16 -0
  143. package/dist/email/driver.d.ts.map +1 -0
  144. package/dist/email/driver.js +136 -0
  145. package/dist/email/driver.js.map +1 -0
  146. package/dist/email/index.d.ts +4 -0
  147. package/dist/email/index.d.ts.map +1 -0
  148. package/dist/email/index.js +4 -0
  149. package/dist/email/index.js.map +1 -0
  150. package/dist/email/shell.d.ts +72 -0
  151. package/dist/email/shell.d.ts.map +1 -0
  152. package/dist/email/shell.js +146 -0
  153. package/dist/email/shell.js.map +1 -0
  154. package/dist/email/templates.d.ts +83 -0
  155. package/dist/email/templates.d.ts.map +1 -0
  156. package/dist/email/templates.js +96 -0
  157. package/dist/email/templates.js.map +1 -0
  158. package/dist/entitlements/check.d.ts +140 -0
  159. package/dist/entitlements/check.d.ts.map +1 -0
  160. package/dist/entitlements/check.js +276 -0
  161. package/dist/entitlements/check.js.map +1 -0
  162. package/dist/entitlements/clock-skew.d.ts +27 -0
  163. package/dist/entitlements/clock-skew.d.ts.map +1 -0
  164. package/dist/entitlements/clock-skew.js +58 -0
  165. package/dist/entitlements/clock-skew.js.map +1 -0
  166. package/dist/entitlements/gate.d.ts +113 -0
  167. package/dist/entitlements/gate.d.ts.map +1 -0
  168. package/dist/entitlements/gate.js +430 -0
  169. package/dist/entitlements/gate.js.map +1 -0
  170. package/dist/entitlements/hub-machine-token.d.ts +83 -0
  171. package/dist/entitlements/hub-machine-token.d.ts.map +1 -0
  172. package/dist/entitlements/hub-machine-token.js +175 -0
  173. package/dist/entitlements/hub-machine-token.js.map +1 -0
  174. package/dist/entitlements/hub-subject.d.ts +32 -0
  175. package/dist/entitlements/hub-subject.d.ts.map +1 -0
  176. package/dist/entitlements/hub-subject.js +68 -0
  177. package/dist/entitlements/hub-subject.js.map +1 -0
  178. package/dist/entitlements/index.d.ts +9 -0
  179. package/dist/entitlements/index.d.ts.map +1 -0
  180. package/dist/entitlements/index.js +9 -0
  181. package/dist/entitlements/index.js.map +1 -0
  182. package/dist/entitlements/poster.d.ts +81 -0
  183. package/dist/entitlements/poster.d.ts.map +1 -0
  184. package/dist/entitlements/poster.js +169 -0
  185. package/dist/entitlements/poster.js.map +1 -0
  186. package/dist/entitlements/profiles.d.ts +121 -0
  187. package/dist/entitlements/profiles.d.ts.map +1 -0
  188. package/dist/entitlements/profiles.js +212 -0
  189. package/dist/entitlements/profiles.js.map +1 -0
  190. package/dist/entitlements/slot.d.ts +33 -0
  191. package/dist/entitlements/slot.d.ts.map +1 -0
  192. package/dist/entitlements/slot.js +75 -0
  193. package/dist/entitlements/slot.js.map +1 -0
  194. package/dist/env.d.ts +293 -0
  195. package/dist/env.d.ts.map +1 -0
  196. package/dist/env.js +383 -0
  197. package/dist/env.js.map +1 -0
  198. package/dist/files/http.d.ts +23 -0
  199. package/dist/files/http.d.ts.map +1 -0
  200. package/dist/files/http.js +66 -0
  201. package/dist/files/http.js.map +1 -0
  202. package/dist/files/index.d.ts +5 -0
  203. package/dist/files/index.d.ts.map +1 -0
  204. package/dist/files/index.js +5 -0
  205. package/dist/files/index.js.map +1 -0
  206. package/dist/files/serve.d.ts +43 -0
  207. package/dist/files/serve.d.ts.map +1 -0
  208. package/dist/files/serve.js +71 -0
  209. package/dist/files/serve.js.map +1 -0
  210. package/dist/files/service.d.ts +69 -0
  211. package/dist/files/service.d.ts.map +1 -0
  212. package/dist/files/service.js +188 -0
  213. package/dist/files/service.js.map +1 -0
  214. package/dist/files/spool.d.ts +21 -0
  215. package/dist/files/spool.d.ts.map +1 -0
  216. package/dist/files/spool.js +47 -0
  217. package/dist/files/spool.js.map +1 -0
  218. package/dist/identity/better-auth.d.ts +3927 -0
  219. package/dist/identity/better-auth.d.ts.map +1 -0
  220. package/dist/identity/better-auth.js +896 -0
  221. package/dist/identity/better-auth.js.map +1 -0
  222. package/dist/identity/demo-pass-plugin.d.ts +29 -0
  223. package/dist/identity/demo-pass-plugin.d.ts.map +1 -0
  224. package/dist/identity/demo-pass-plugin.js +88 -0
  225. package/dist/identity/demo-pass-plugin.js.map +1 -0
  226. package/dist/identity/demo-pass-rules.d.ts +84 -0
  227. package/dist/identity/demo-pass-rules.d.ts.map +1 -0
  228. package/dist/identity/demo-pass-rules.js +223 -0
  229. package/dist/identity/demo-pass-rules.js.map +1 -0
  230. package/dist/identity/demo-pass.d.ts +159 -0
  231. package/dist/identity/demo-pass.d.ts.map +1 -0
  232. package/dist/identity/demo-pass.js +319 -0
  233. package/dist/identity/demo-pass.js.map +1 -0
  234. package/dist/identity/hub-grant.d.ts +182 -0
  235. package/dist/identity/hub-grant.d.ts.map +1 -0
  236. package/dist/identity/hub-grant.js +594 -0
  237. package/dist/identity/hub-grant.js.map +1 -0
  238. package/dist/identity/hub-jwt.d.ts +22 -0
  239. package/dist/identity/hub-jwt.d.ts.map +1 -0
  240. package/dist/identity/hub-jwt.js +77 -0
  241. package/dist/identity/hub-jwt.js.map +1 -0
  242. package/dist/identity/hub-live-gate.d.ts +17 -0
  243. package/dist/identity/hub-live-gate.d.ts.map +1 -0
  244. package/dist/identity/hub-live-gate.js +146 -0
  245. package/dist/identity/hub-live-gate.js.map +1 -0
  246. package/dist/identity/hub-logout.d.ts +88 -0
  247. package/dist/identity/hub-logout.d.ts.map +1 -0
  248. package/dist/identity/hub-logout.js +158 -0
  249. package/dist/identity/hub-logout.js.map +1 -0
  250. package/dist/identity/hub-projection.d.ts +103 -0
  251. package/dist/identity/hub-projection.d.ts.map +1 -0
  252. package/dist/identity/hub-projection.js +130 -0
  253. package/dist/identity/hub-projection.js.map +1 -0
  254. package/dist/identity/hub-reconcile.d.ts +151 -0
  255. package/dist/identity/hub-reconcile.d.ts.map +1 -0
  256. package/dist/identity/hub-reconcile.js +400 -0
  257. package/dist/identity/hub-reconcile.js.map +1 -0
  258. package/dist/identity/hub-sso.d.ts +363 -0
  259. package/dist/identity/hub-sso.d.ts.map +1 -0
  260. package/dist/identity/hub-sso.js +536 -0
  261. package/dist/identity/hub-sso.js.map +1 -0
  262. package/dist/identity/hub-user-client.d.ts +222 -0
  263. package/dist/identity/hub-user-client.d.ts.map +1 -0
  264. package/dist/identity/hub-user-client.js +406 -0
  265. package/dist/identity/hub-user-client.js.map +1 -0
  266. package/dist/identity/index.d.ts +13 -0
  267. package/dist/identity/index.d.ts.map +1 -0
  268. package/dist/identity/index.js +13 -0
  269. package/dist/identity/index.js.map +1 -0
  270. package/dist/identity/oauth-jwt.d.ts +32 -0
  271. package/dist/identity/oauth-jwt.d.ts.map +1 -0
  272. package/dist/identity/oauth-jwt.js +122 -0
  273. package/dist/identity/oauth-jwt.js.map +1 -0
  274. package/dist/identity/resolve-membership.d.ts +28 -0
  275. package/dist/identity/resolve-membership.d.ts.map +1 -0
  276. package/dist/identity/resolve-membership.js +69 -0
  277. package/dist/identity/resolve-membership.js.map +1 -0
  278. package/dist/identity/signing-key.d.ts +49 -0
  279. package/dist/identity/signing-key.d.ts.map +1 -0
  280. package/dist/identity/signing-key.js +144 -0
  281. package/dist/identity/signing-key.js.map +1 -0
  282. package/dist/index.d.ts +21 -0
  283. package/dist/index.d.ts.map +1 -0
  284. package/dist/index.js +11 -0
  285. package/dist/index.js.map +1 -0
  286. package/dist/invitations/index.d.ts +2 -0
  287. package/dist/invitations/index.d.ts.map +1 -0
  288. package/dist/invitations/index.js +2 -0
  289. package/dist/invitations/index.js.map +1 -0
  290. package/dist/invitations/service.d.ts +36 -0
  291. package/dist/invitations/service.d.ts.map +1 -0
  292. package/dist/invitations/service.js +122 -0
  293. package/dist/invitations/service.js.map +1 -0
  294. package/dist/jobs/index.d.ts +3 -0
  295. package/dist/jobs/index.d.ts.map +1 -0
  296. package/dist/jobs/index.js +3 -0
  297. package/dist/jobs/index.js.map +1 -0
  298. package/dist/jobs/pgboss.d.ts +119 -0
  299. package/dist/jobs/pgboss.d.ts.map +1 -0
  300. package/dist/jobs/pgboss.js +521 -0
  301. package/dist/jobs/pgboss.js.map +1 -0
  302. package/dist/jobs/timers.d.ts +127 -0
  303. package/dist/jobs/timers.d.ts.map +1 -0
  304. package/dist/jobs/timers.js +228 -0
  305. package/dist/jobs/timers.js.map +1 -0
  306. package/dist/logger.d.ts +17 -0
  307. package/dist/logger.d.ts.map +1 -0
  308. package/dist/logger.js +64 -0
  309. package/dist/logger.js.map +1 -0
  310. package/dist/mcp/errors.d.ts +37 -0
  311. package/dist/mcp/errors.d.ts.map +1 -0
  312. package/dist/mcp/errors.js +77 -0
  313. package/dist/mcp/errors.js.map +1 -0
  314. package/dist/mcp/http.d.ts +35 -0
  315. package/dist/mcp/http.d.ts.map +1 -0
  316. package/dist/mcp/http.js +80 -0
  317. package/dist/mcp/http.js.map +1 -0
  318. package/dist/mcp/index.d.ts +8 -0
  319. package/dist/mcp/index.d.ts.map +1 -0
  320. package/dist/mcp/index.js +8 -0
  321. package/dist/mcp/index.js.map +1 -0
  322. package/dist/mcp/inputs.d.ts +19 -0
  323. package/dist/mcp/inputs.d.ts.map +1 -0
  324. package/dist/mcp/inputs.js +28 -0
  325. package/dist/mcp/inputs.js.map +1 -0
  326. package/dist/mcp/projects.d.ts +31 -0
  327. package/dist/mcp/projects.d.ts.map +1 -0
  328. package/dist/mcp/projects.js +315 -0
  329. package/dist/mcp/projects.js.map +1 -0
  330. package/dist/mcp/server.d.ts +52 -0
  331. package/dist/mcp/server.d.ts.map +1 -0
  332. package/dist/mcp/server.js +93 -0
  333. package/dist/mcp/server.js.map +1 -0
  334. package/dist/mcp/teams.d.ts +7 -0
  335. package/dist/mcp/teams.d.ts.map +1 -0
  336. package/dist/mcp/teams.js +62 -0
  337. package/dist/mcp/teams.js.map +1 -0
  338. package/dist/mcp/tool-kit.d.ts +67 -0
  339. package/dist/mcp/tool-kit.d.ts.map +1 -0
  340. package/dist/mcp/tool-kit.js +74 -0
  341. package/dist/mcp/tool-kit.js.map +1 -0
  342. package/dist/members/removal.d.ts +95 -0
  343. package/dist/members/removal.d.ts.map +1 -0
  344. package/dist/members/removal.js +143 -0
  345. package/dist/members/removal.js.map +1 -0
  346. package/dist/middleware/auth-body.d.ts +25 -0
  347. package/dist/middleware/auth-body.d.ts.map +1 -0
  348. package/dist/middleware/auth-body.js +55 -0
  349. package/dist/middleware/auth-body.js.map +1 -0
  350. package/dist/middleware/auth-context.d.ts +170 -0
  351. package/dist/middleware/auth-context.d.ts.map +1 -0
  352. package/dist/middleware/auth-context.js +251 -0
  353. package/dist/middleware/auth-context.js.map +1 -0
  354. package/dist/middleware/body-cap.d.ts +17 -0
  355. package/dist/middleware/body-cap.d.ts.map +1 -0
  356. package/dist/middleware/body-cap.js +31 -0
  357. package/dist/middleware/body-cap.js.map +1 -0
  358. package/dist/middleware/body-refusal.d.ts +20 -0
  359. package/dist/middleware/body-refusal.d.ts.map +1 -0
  360. package/dist/middleware/body-refusal.js +5 -0
  361. package/dist/middleware/body-refusal.js.map +1 -0
  362. package/dist/middleware/cross-site.d.ts +61 -0
  363. package/dist/middleware/cross-site.d.ts.map +1 -0
  364. package/dist/middleware/cross-site.js +59 -0
  365. package/dist/middleware/cross-site.js.map +1 -0
  366. package/dist/middleware/hub-managed.d.ts +45 -0
  367. package/dist/middleware/hub-managed.d.ts.map +1 -0
  368. package/dist/middleware/hub-managed.js +56 -0
  369. package/dist/middleware/hub-managed.js.map +1 -0
  370. package/dist/middleware/idempotency.d.ts +14 -0
  371. package/dist/middleware/idempotency.d.ts.map +1 -0
  372. package/dist/middleware/idempotency.js +222 -0
  373. package/dist/middleware/idempotency.js.map +1 -0
  374. package/dist/middleware/index.d.ts +12 -0
  375. package/dist/middleware/index.d.ts.map +1 -0
  376. package/dist/middleware/index.js +12 -0
  377. package/dist/middleware/index.js.map +1 -0
  378. package/dist/middleware/json-depth.d.ts +32 -0
  379. package/dist/middleware/json-depth.d.ts.map +1 -0
  380. package/dist/middleware/json-depth.js +80 -0
  381. package/dist/middleware/json-depth.js.map +1 -0
  382. package/dist/middleware/no-store.d.ts +21 -0
  383. package/dist/middleware/no-store.d.ts.map +1 -0
  384. package/dist/middleware/no-store.js +32 -0
  385. package/dist/middleware/no-store.js.map +1 -0
  386. package/dist/middleware/oauth-public.d.ts +16 -0
  387. package/dist/middleware/oauth-public.d.ts.map +1 -0
  388. package/dist/middleware/oauth-public.js +50 -0
  389. package/dist/middleware/oauth-public.js.map +1 -0
  390. package/dist/middleware/rate-limit.d.ts +182 -0
  391. package/dist/middleware/rate-limit.d.ts.map +1 -0
  392. package/dist/middleware/rate-limit.js +277 -0
  393. package/dist/middleware/rate-limit.js.map +1 -0
  394. package/dist/middleware/request-id.d.ts +10 -0
  395. package/dist/middleware/request-id.d.ts.map +1 -0
  396. package/dist/middleware/request-id.js +42 -0
  397. package/dist/middleware/request-id.js.map +1 -0
  398. package/dist/middleware/scopes.d.ts +33 -0
  399. package/dist/middleware/scopes.d.ts.map +1 -0
  400. package/dist/middleware/scopes.js +139 -0
  401. package/dist/middleware/scopes.js.map +1 -0
  402. package/dist/middleware/security-headers.d.ts +53 -0
  403. package/dist/middleware/security-headers.d.ts.map +1 -0
  404. package/dist/middleware/security-headers.js +96 -0
  405. package/dist/middleware/security-headers.js.map +1 -0
  406. package/dist/observability/index.d.ts +3 -0
  407. package/dist/observability/index.d.ts.map +1 -0
  408. package/dist/observability/index.js +3 -0
  409. package/dist/observability/index.js.map +1 -0
  410. package/dist/observability/metrics.d.ts +17 -0
  411. package/dist/observability/metrics.d.ts.map +1 -0
  412. package/dist/observability/metrics.js +82 -0
  413. package/dist/observability/metrics.js.map +1 -0
  414. package/dist/observability/otel.d.ts +20 -0
  415. package/dist/observability/otel.d.ts.map +1 -0
  416. package/dist/observability/otel.js +54 -0
  417. package/dist/observability/otel.js.map +1 -0
  418. package/dist/pagination.d.ts +57 -0
  419. package/dist/pagination.d.ts.map +1 -0
  420. package/dist/pagination.js +90 -0
  421. package/dist/pagination.js.map +1 -0
  422. package/dist/platform/edition.d.ts +57 -0
  423. package/dist/platform/edition.d.ts.map +1 -0
  424. package/dist/platform/edition.js +90 -0
  425. package/dist/platform/edition.js.map +1 -0
  426. package/dist/platform/entitlements.d.ts +26 -0
  427. package/dist/platform/entitlements.d.ts.map +1 -0
  428. package/dist/platform/entitlements.js +28 -0
  429. package/dist/platform/entitlements.js.map +1 -0
  430. package/dist/platform/events.d.ts +87 -0
  431. package/dist/platform/events.d.ts.map +1 -0
  432. package/dist/platform/events.js +32 -0
  433. package/dist/platform/events.js.map +1 -0
  434. package/dist/platform/index.d.ts +8 -0
  435. package/dist/platform/index.d.ts.map +1 -0
  436. package/dist/platform/index.js +8 -0
  437. package/dist/platform/index.js.map +1 -0
  438. package/dist/platform/local-identity.d.ts +39 -0
  439. package/dist/platform/local-identity.d.ts.map +1 -0
  440. package/dist/platform/local-identity.js +87 -0
  441. package/dist/platform/local-identity.js.map +1 -0
  442. package/dist/platform/registry.d.ts +23 -0
  443. package/dist/platform/registry.d.ts.map +1 -0
  444. package/dist/platform/registry.js +5 -0
  445. package/dist/platform/registry.js.map +1 -0
  446. package/dist/platform/usage.d.ts +11 -0
  447. package/dist/platform/usage.d.ts.map +1 -0
  448. package/dist/platform/usage.js +12 -0
  449. package/dist/platform/usage.js.map +1 -0
  450. package/dist/platform/workspaces.d.ts +25 -0
  451. package/dist/platform/workspaces.d.ts.map +1 -0
  452. package/dist/platform/workspaces.js +44 -0
  453. package/dist/platform/workspaces.js.map +1 -0
  454. package/dist/projects/access.d.ts +40 -0
  455. package/dist/projects/access.d.ts.map +1 -0
  456. package/dist/projects/access.js +133 -0
  457. package/dist/projects/access.js.map +1 -0
  458. package/dist/projects/index.d.ts +2 -0
  459. package/dist/projects/index.d.ts.map +1 -0
  460. package/dist/projects/index.js +2 -0
  461. package/dist/projects/index.js.map +1 -0
  462. package/dist/route-label.d.ts +23 -0
  463. package/dist/route-label.d.ts.map +1 -0
  464. package/dist/route-label.js +29 -0
  465. package/dist/route-label.js.map +1 -0
  466. package/dist/routes/health.d.ts +30 -0
  467. package/dist/routes/health.d.ts.map +1 -0
  468. package/dist/routes/health.js +54 -0
  469. package/dist/routes/health.js.map +1 -0
  470. package/dist/routes/index.d.ts +3 -0
  471. package/dist/routes/index.d.ts.map +1 -0
  472. package/dist/routes/index.js +3 -0
  473. package/dist/routes/index.js.map +1 -0
  474. package/dist/routes/wellknown.d.ts +11 -0
  475. package/dist/routes/wellknown.d.ts.map +1 -0
  476. package/dist/routes/wellknown.js +45 -0
  477. package/dist/routes/wellknown.js.map +1 -0
  478. package/dist/secret.d.ts +30 -0
  479. package/dist/secret.d.ts.map +1 -0
  480. package/dist/secret.js +97 -0
  481. package/dist/secret.js.map +1 -0
  482. package/dist/setup-transport.d.ts +23 -0
  483. package/dist/setup-transport.d.ts.map +1 -0
  484. package/dist/setup-transport.js +52 -0
  485. package/dist/setup-transport.js.map +1 -0
  486. package/dist/state.d.ts +21 -0
  487. package/dist/state.d.ts.map +1 -0
  488. package/dist/state.js +4 -0
  489. package/dist/state.js.map +1 -0
  490. package/dist/storage/driver.d.ts +38 -0
  491. package/dist/storage/driver.d.ts.map +1 -0
  492. package/dist/storage/driver.js +14 -0
  493. package/dist/storage/driver.js.map +1 -0
  494. package/dist/storage/factory.d.ts +4 -0
  495. package/dist/storage/factory.d.ts.map +1 -0
  496. package/dist/storage/factory.js +20 -0
  497. package/dist/storage/factory.js.map +1 -0
  498. package/dist/storage/index.d.ts +4 -0
  499. package/dist/storage/index.d.ts.map +1 -0
  500. package/dist/storage/index.js +4 -0
  501. package/dist/storage/index.js.map +1 -0
  502. package/dist/storage/local.d.ts +21 -0
  503. package/dist/storage/local.d.ts.map +1 -0
  504. package/dist/storage/local.js +88 -0
  505. package/dist/storage/local.js.map +1 -0
  506. package/dist/storage/s3.d.ts +29 -0
  507. package/dist/storage/s3.d.ts.map +1 -0
  508. package/dist/storage/s3.js +82 -0
  509. package/dist/storage/s3.js.map +1 -0
  510. package/dist/testing/fake-hub.d.ts +425 -0
  511. package/dist/testing/fake-hub.d.ts.map +1 -0
  512. package/dist/testing/fake-hub.js +1074 -0
  513. package/dist/testing/fake-hub.js.map +1 -0
  514. package/dist/testing/helpers.d.ts +124 -0
  515. package/dist/testing/helpers.d.ts.map +1 -0
  516. package/dist/testing/helpers.js +174 -0
  517. package/dist/testing/helpers.js.map +1 -0
  518. package/dist/testing/index.d.ts +12 -0
  519. package/dist/testing/index.d.ts.map +1 -0
  520. package/dist/testing/index.js +12 -0
  521. package/dist/testing/index.js.map +1 -0
  522. package/dist/testing/setup-origins.d.ts +21 -0
  523. package/dist/testing/setup-origins.d.ts.map +1 -0
  524. package/dist/testing/setup-origins.js +57 -0
  525. package/dist/testing/setup-origins.js.map +1 -0
  526. package/dist/testing/sso-helpers.d.ts +43 -0
  527. package/dist/testing/sso-helpers.d.ts.map +1 -0
  528. package/dist/testing/sso-helpers.js +159 -0
  529. package/dist/testing/sso-helpers.js.map +1 -0
  530. package/dist/tool-definition.d.ts +382 -0
  531. package/dist/tool-definition.d.ts.map +1 -0
  532. package/dist/tool-definition.js +46 -0
  533. package/dist/tool-definition.js.map +1 -0
  534. package/dist/util/index.d.ts +8 -0
  535. package/dist/util/index.d.ts.map +1 -0
  536. package/dist/util/index.js +8 -0
  537. package/dist/util/index.js.map +1 -0
  538. package/package.json +161 -0
  539. package/src/accounts/deletion.ts +389 -0
  540. package/src/accounts/erasure-log.ts +140 -0
  541. package/src/accounts/index.ts +5 -0
  542. package/src/accounts/mint-refusal.ts +67 -0
  543. package/src/accounts/signup-duplicate.ts +21 -0
  544. package/src/accounts/superadmin.ts +46 -0
  545. package/src/api/apikeys.ts +147 -0
  546. package/src/api/audit.ts +83 -0
  547. package/src/api/break-glass.ts +294 -0
  548. package/src/api/cli-auth.ts +308 -0
  549. package/src/api/create-api.ts +1403 -0
  550. package/src/api/demo-passes.ts +207 -0
  551. package/src/api/errors.ts +13 -0
  552. package/src/api/export.ts +482 -0
  553. package/src/api/files.ts +200 -0
  554. package/src/api/index.ts +29 -0
  555. package/src/api/invitations.ts +396 -0
  556. package/src/api/members.ts +617 -0
  557. package/src/api/onboarding.ts +50 -0
  558. package/src/api/openapi-doc.ts +34 -0
  559. package/src/api/projects.ts +788 -0
  560. package/src/api/scope-routes.ts +12 -0
  561. package/src/api/sso-connect.ts +246 -0
  562. package/src/api/sso-logout.ts +76 -0
  563. package/src/api/teams.ts +575 -0
  564. package/src/api/workspaces.ts +649 -0
  565. package/src/apikeys/index.ts +2 -0
  566. package/src/apikeys/peppers.ts +118 -0
  567. package/src/apikeys/service.ts +223 -0
  568. package/src/app.ts +228 -0
  569. package/src/audit/filters.ts +101 -0
  570. package/src/audit/index.ts +9 -0
  571. package/src/audit/service.ts +154 -0
  572. package/src/boot.ts +953 -0
  573. package/src/constant-time.ts +9 -0
  574. package/src/email/driver.ts +139 -0
  575. package/src/email/index.ts +26 -0
  576. package/src/email/shell.ts +201 -0
  577. package/src/email/templates.ts +184 -0
  578. package/src/entitlements/check.ts +435 -0
  579. package/src/entitlements/clock-skew.ts +58 -0
  580. package/src/entitlements/gate.ts +636 -0
  581. package/src/entitlements/hub-machine-token.ts +205 -0
  582. package/src/entitlements/hub-subject.ts +77 -0
  583. package/src/entitlements/index.ts +37 -0
  584. package/src/entitlements/poster.ts +265 -0
  585. package/src/entitlements/profiles.ts +303 -0
  586. package/src/entitlements/slot.ts +105 -0
  587. package/src/env.ts +456 -0
  588. package/src/files/http.ts +77 -0
  589. package/src/files/index.ts +4 -0
  590. package/src/files/serve.ts +115 -0
  591. package/src/files/service.ts +209 -0
  592. package/src/files/spool.ts +58 -0
  593. package/src/identity/better-auth.ts +1103 -0
  594. package/src/identity/demo-pass-plugin.ts +121 -0
  595. package/src/identity/demo-pass-rules.ts +229 -0
  596. package/src/identity/demo-pass.ts +390 -0
  597. package/src/identity/hub-grant.ts +704 -0
  598. package/src/identity/hub-jwt.ts +78 -0
  599. package/src/identity/hub-live-gate.ts +167 -0
  600. package/src/identity/hub-logout.ts +174 -0
  601. package/src/identity/hub-projection.ts +251 -0
  602. package/src/identity/hub-reconcile.ts +572 -0
  603. package/src/identity/hub-sso.ts +696 -0
  604. package/src/identity/hub-user-client.ts +554 -0
  605. package/src/identity/index.ts +56 -0
  606. package/src/identity/oauth-jwt.ts +128 -0
  607. package/src/identity/resolve-membership.ts +104 -0
  608. package/src/identity/signing-key.ts +164 -0
  609. package/src/index.ts +65 -0
  610. package/src/invitations/index.ts +1 -0
  611. package/src/invitations/service.ts +171 -0
  612. package/src/jobs/index.ts +25 -0
  613. package/src/jobs/pgboss.ts +594 -0
  614. package/src/jobs/timers.ts +287 -0
  615. package/src/logger.ts +67 -0
  616. package/src/mcp/errors.ts +111 -0
  617. package/src/mcp/http.ts +129 -0
  618. package/src/mcp/index.ts +28 -0
  619. package/src/mcp/inputs.ts +33 -0
  620. package/src/mcp/projects.ts +480 -0
  621. package/src/mcp/server.ts +174 -0
  622. package/src/mcp/teams.ts +97 -0
  623. package/src/mcp/tool-kit.ts +148 -0
  624. package/src/members/removal.ts +216 -0
  625. package/src/middleware/auth-body.ts +58 -0
  626. package/src/middleware/auth-context.ts +384 -0
  627. package/src/middleware/body-cap.ts +33 -0
  628. package/src/middleware/body-refusal.ts +23 -0
  629. package/src/middleware/cross-site.ts +122 -0
  630. package/src/middleware/hub-managed.ts +61 -0
  631. package/src/middleware/idempotency.ts +264 -0
  632. package/src/middleware/index.ts +33 -0
  633. package/src/middleware/json-depth.ts +74 -0
  634. package/src/middleware/no-store.ts +30 -0
  635. package/src/middleware/oauth-public.ts +54 -0
  636. package/src/middleware/rate-limit.ts +432 -0
  637. package/src/middleware/request-id.ts +54 -0
  638. package/src/middleware/scopes.ts +150 -0
  639. package/src/middleware/security-headers.ts +129 -0
  640. package/src/observability/index.ts +2 -0
  641. package/src/observability/metrics.ts +102 -0
  642. package/src/observability/otel.ts +79 -0
  643. package/src/pagination.ts +118 -0
  644. package/src/platform/edition.ts +140 -0
  645. package/src/platform/entitlements.ts +47 -0
  646. package/src/platform/events.ts +71 -0
  647. package/src/platform/index.ts +7 -0
  648. package/src/platform/local-identity.ts +90 -0
  649. package/src/platform/registry.ts +28 -0
  650. package/src/platform/usage.ts +13 -0
  651. package/src/platform/workspaces.ts +41 -0
  652. package/src/projects/access.ts +160 -0
  653. package/src/projects/index.ts +7 -0
  654. package/src/route-label.ts +29 -0
  655. package/src/routes/health.ts +79 -0
  656. package/src/routes/index.ts +2 -0
  657. package/src/routes/wellknown.ts +67 -0
  658. package/src/secret.ts +115 -0
  659. package/src/setup-transport.ts +46 -0
  660. package/src/state.ts +23 -0
  661. package/src/storage/driver.ts +48 -0
  662. package/src/storage/factory.ts +34 -0
  663. package/src/storage/index.ts +3 -0
  664. package/src/storage/local.ts +93 -0
  665. package/src/storage/s3.ts +109 -0
  666. package/src/testing/fake-hub.ts +1316 -0
  667. package/src/testing/helpers.ts +254 -0
  668. package/src/testing/index.ts +11 -0
  669. package/src/testing/setup-origins.ts +58 -0
  670. package/src/testing/sso-helpers.ts +178 -0
  671. package/src/tool-definition.ts +463 -0
  672. package/src/util/index.ts +17 -0
  673. package/test/fixtures/onboarding-backfill.sql +13 -0
  674. package/test/fixtures/operator-user-id-backfill.sql +18 -0
  675. package/test/host/dr-lib.sh +253 -0
  676. package/test/host/drizzle/0000_chassis_baseline.sql +438 -0
  677. package/test/host/drizzle/0001_last_owner_guard.sql +42 -0
  678. package/test/host/drizzle/meta/0000_snapshot.json +3566 -0
  679. package/test/host/drizzle/meta/_journal.json +20 -0
  680. package/test/host/drizzle.config.ts +17 -0
  681. package/test/host/identity.ts +41 -0
  682. package/test/host/minimal-host.ts +35 -0
  683. package/test/host/minimal-tool.ts +123 -0
  684. package/test/integration/account-oracle-uniformity.test.ts +284 -0
  685. package/test/integration/account-recovery.test.ts +236 -0
  686. package/test/integration/account.test.ts +120 -0
  687. package/test/integration/api-quota.test.ts +208 -0
  688. package/test/integration/apikey-expiry.test.ts +178 -0
  689. package/test/integration/apikey-pepper-rotation.test.ts +190 -0
  690. package/test/integration/boot-posture.test.ts +169 -0
  691. package/test/integration/break-glass.test.ts +484 -0
  692. package/test/integration/cloud-lifecycle.test.ts +233 -0
  693. package/test/integration/credential-boundaries.test.ts +195 -0
  694. package/test/integration/default-workspace.test.ts +414 -0
  695. package/test/integration/demo-pass-rules.test.ts +332 -0
  696. package/test/integration/demo-pass.test.ts +1222 -0
  697. package/test/integration/dr-verify-real-dump.test.ts +154 -0
  698. package/test/integration/edition.test.ts +868 -0
  699. package/test/integration/email-change.test.ts +394 -0
  700. package/test/integration/empty-tool.test.ts +267 -0
  701. package/test/integration/entitlements-null-hook.test.ts +187 -0
  702. package/test/integration/entitlements.test.ts +693 -0
  703. package/test/integration/export-entries.test.ts +321 -0
  704. package/test/integration/files.test.ts +320 -0
  705. package/test/integration/first-boot-claim.test.ts +131 -0
  706. package/test/integration/gdpr.test.ts +532 -0
  707. package/test/integration/helpers.ts +29 -0
  708. package/test/integration/hub-grant.test.ts +505 -0
  709. package/test/integration/hub-live-gate.test.ts +612 -0
  710. package/test/integration/hub-managed-membership.test.ts +559 -0
  711. package/test/integration/hub-org-selector.test.ts +281 -0
  712. package/test/integration/hub-reconcile.test.ts +646 -0
  713. package/test/integration/hub-sso.test.ts +704 -0
  714. package/test/integration/hub-teams.test.ts +771 -0
  715. package/test/integration/idempotency.test.ts +261 -0
  716. package/test/integration/invite-verification.test.ts +210 -0
  717. package/test/integration/last-owner-race.test.ts +263 -0
  718. package/test/integration/m9-fixes.test.ts +290 -0
  719. package/test/integration/mcp-projects.test.ts +463 -0
  720. package/test/integration/member-removal-race.test.ts +466 -0
  721. package/test/integration/member-removal.test.ts +794 -0
  722. package/test/integration/oauth-mcp.test.ts +477 -0
  723. package/test/integration/oauth-workspace.test.ts +371 -0
  724. package/test/integration/observability.test.ts +183 -0
  725. package/test/integration/onboarding.test.ts +268 -0
  726. package/test/integration/orphan-purge.test.ts +451 -0
  727. package/test/integration/pagination.test.ts +344 -0
  728. package/test/integration/platform-core.test.ts +305 -0
  729. package/test/integration/platform.test.ts +246 -0
  730. package/test/integration/pool-survives-restart.test.ts +80 -0
  731. package/test/integration/projects-cloud.test.ts +193 -0
  732. package/test/integration/projects.test.ts +1310 -0
  733. package/test/integration/security-fixes.test.ts +190 -0
  734. package/test/integration/setup-transport.test.ts +118 -0
  735. package/test/integration/signin-wall.test.ts +103 -0
  736. package/test/integration/signing-key-rotation.test.ts +349 -0
  737. package/test/integration/sso-helpers.ts +15 -0
  738. package/test/integration/sso-logout.test.ts +283 -0
  739. package/test/integration/teams-cloud.test.ts +194 -0
  740. package/test/integration/teams.test.ts +551 -0
  741. package/test/integration/timers.test.ts +377 -0
  742. package/test/integration/two-factor.test.ts +301 -0
  743. package/test/integration/usage-window.test.ts +161 -0
  744. package/test/integration/workspace-create-cloud.test.ts +523 -0
  745. package/test/integration/workspace-create.test.ts +510 -0
  746. package/test/integration/workspace-scoping.test.ts +530 -0
  747. package/test/integration/zz-adv-replay-owner.test.ts +205 -0
  748. package/test/unit/apikey-peppers.test.ts +110 -0
  749. package/test/unit/apikey-prefix.test.ts +34 -0
  750. package/test/unit/audit-filters.test.ts +135 -0
  751. package/test/unit/auth-origins.test.ts +92 -0
  752. package/test/unit/body-cap.test.ts +84 -0
  753. package/test/unit/clock-skew.test.ts +68 -0
  754. package/test/unit/cross-site.test.ts +166 -0
  755. package/test/unit/declared-credits.test.ts +13 -0
  756. package/test/unit/demo-pass-rules.test.ts +192 -0
  757. package/test/unit/email-driver.test.ts +127 -0
  758. package/test/unit/end-pool.test.ts +181 -0
  759. package/test/unit/entitlement-check.test.ts +492 -0
  760. package/test/unit/entitlement-gate.test.ts +1333 -0
  761. package/test/unit/entitlement-profiles.test.ts +289 -0
  762. package/test/unit/erasure-log.test.ts +72 -0
  763. package/test/unit/error-mapping.test.ts +89 -0
  764. package/test/unit/export-entries.test.ts +85 -0
  765. package/test/unit/export-sanitize.test.ts +27 -0
  766. package/test/unit/files-head-route.test.ts +155 -0
  767. package/test/unit/files-http.test.ts +97 -0
  768. package/test/unit/head-rewrite.test.ts +72 -0
  769. package/test/unit/hub-create-org.test.ts +181 -0
  770. package/test/unit/hub-jwt.test.ts +93 -0
  771. package/test/unit/hub-sso-params.test.ts +39 -0
  772. package/test/unit/hub-subject.test.ts +83 -0
  773. package/test/unit/idempotency-crypto.test.ts +45 -0
  774. package/test/unit/json-depth.test.ts +88 -0
  775. package/test/unit/logger-redaction.test.ts +66 -0
  776. package/test/unit/mcp-errors.test.ts +110 -0
  777. package/test/unit/mcp-inputs.test.ts +106 -0
  778. package/test/unit/mcp-project-hints.test.ts +26 -0
  779. package/test/unit/no-store.test.ts +49 -0
  780. package/test/unit/no-tool-migration-filename.test.ts +70 -0
  781. package/test/unit/observability.test.ts +64 -0
  782. package/test/unit/openapi-doc.test.ts +93 -0
  783. package/test/unit/rate-limit-consume-on.test.ts +76 -0
  784. package/test/unit/rate-limit.test.ts +39 -0
  785. package/test/unit/readyz-storage.test.ts +157 -0
  786. package/test/unit/request-quota.test.ts +146 -0
  787. package/test/unit/scopes.test.ts +66 -0
  788. package/test/unit/security-headers.test.ts +131 -0
  789. package/test/unit/serve-content-type.test.ts +74 -0
  790. package/test/unit/setup-transport.test.ts +29 -0
  791. package/test/unit/storage-local.test.ts +53 -0
  792. package/test/unit/superadmin.test.ts +32 -0
  793. package/test/unit/timers.test.ts +287 -0
  794. package/test/unit/tool-definition-guards.test.ts +166 -0
  795. package/test/unit/tool-entitlements-guard.test.ts +168 -0
  796. package/test/unit/usage-poster.test.ts +542 -0
  797. package/test/unit/usage-window.test.ts +48 -0
  798. package/test/unit/workspace-create-audit.test.ts +48 -0
@@ -0,0 +1,71 @@
1
+ import type { Logger } from '../logger.js';
2
+
3
+ /**
4
+ * Internal event bus: domain modules publish, platform modules (and later
5
+ * rail/ee modules registered at boot) subscribe. Deliberately synchronous
6
+ * fan-out with error isolation — a failing subscriber never breaks the
7
+ * publisher's request path.
8
+ */
9
+ export type PlatformEvents = {
10
+ /**
11
+ * Fired by the identity layer (Better Auth databaseHooks.user.create.after,
12
+ * wired in boot) for EVERY account entrance — setup, invitation accept,
13
+ * collaborator claim, future SSO JIT. Trustworthy by construction; call
14
+ * sites never emit it.
15
+ */
16
+ 'user.created': { userId: string; email: string };
17
+ 'member.joined': { workspaceId: string; userId: string; role: string };
18
+ 'member.updated': { workspaceId: string; userId: string };
19
+ 'member.removed': { workspaceId: string; userId: string };
20
+ 'apikey.created': { workspaceId: string; apiKeyId: string };
21
+ 'apikey.revoked': { workspaceId: string; apiKeyId: string };
22
+ 'invitation.created': { workspaceId: string; invitationId: string };
23
+ 'invitation.accepted': { workspaceId: string; invitationId: string; userId: string };
24
+ 'file.uploaded': { workspaceId: string; fileId: string; sizeBytes: number };
25
+ /** workspaceId is null on the cloud edition — setup creates no workspace there. */
26
+ /** A person created ANOTHER workspace from inside the product (POST /workspaces). */
27
+ 'workspace.created': { workspaceId: string; ownerUserId: string };
28
+ 'setup.completed': { workspaceId: string | null; instanceId: string };
29
+ };
30
+
31
+ /**
32
+ * The events a bus carries: the chassis ones plus the tool's own (`TExtra`, a
33
+ * map of event name to payload, declared by the tool that instantiates the bus).
34
+ */
35
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
36
+ export type EventMap<TExtra = {}> = PlatformEvents & TExtra;
37
+
38
+ type Handler<M, E extends keyof M> = (payload: M[E]) => void | Promise<void>;
39
+
40
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
41
+ export class EventBus<TExtra = {}> {
42
+ private handlers = new Map<keyof EventMap<TExtra>, Set<Handler<EventMap<TExtra>, never>>>();
43
+
44
+ constructor(private readonly logger: Logger) {}
45
+
46
+ on<E extends keyof EventMap<TExtra>>(event: E, handler: Handler<EventMap<TExtra>, E>): () => void {
47
+ const set = this.handlers.get(event) ?? new Set();
48
+ set.add(handler as Handler<EventMap<TExtra>, never>);
49
+ this.handlers.set(event, set);
50
+ return () => set.delete(handler as Handler<EventMap<TExtra>, never>);
51
+ }
52
+
53
+ /**
54
+ * The SAME bus as the chassis sees it: the generic events only. The
55
+ * composition code is generic over the tool's event map, and a bus is
56
+ * invariant in it (it both takes and hands out payloads), so the chassis
57
+ * modules, written against the generic map, read the bus through this view.
58
+ * Sound as long as a tool never re-declares a chassis event name.
59
+ */
60
+ chassisView(): EventBus {
61
+ return this as unknown as EventBus;
62
+ }
63
+
64
+ emit<E extends keyof EventMap<TExtra>>(event: E, payload: EventMap<TExtra>[E]): void {
65
+ for (const handler of this.handlers.get(event) ?? []) {
66
+ Promise.resolve((handler as Handler<EventMap<TExtra>, E>)(payload)).catch((err) => {
67
+ this.logger.error({ err, event }, 'event handler failed');
68
+ });
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,7 @@
1
+ export { AllowAllEntitlements } from './entitlements.js';
2
+ export { EventBus } from './events.js';
3
+ export { type PlatformRegistry, createRegistry } from './registry.js';
4
+ export { NoopUsageSink } from './usage.js';
5
+ export { WorkspaceService } from './workspaces.js';
6
+ export { bindEditionSeams } from './edition.js';
7
+ export { LocalIdentityProvider } from './local-identity.js';
@@ -0,0 +1,90 @@
1
+ import { type Db } from '@antasphere/chassis-db';
2
+ import {
3
+ ACTIVE_WORKSPACE_HEADER,
4
+ type IdentityProvider,
5
+ type InstanceAuthDescriptor,
6
+ type Principal,
7
+ type RequestContext
8
+ } from '@antasphere/chassis-contract';
9
+ import type { Auth } from '../identity/better-auth.js';
10
+ import {
11
+ isWorkspaceSelector,
12
+ resolveMembership,
13
+ type OnWorkspaceMiss
14
+ } from '../identity/resolve-membership.js';
15
+
16
+ /**
17
+ * The template's default IdentityProvider: Better Auth sessions + a LIVE
18
+ * workspace_members re-check on every request. The membership row — not the
19
+ * cookie — is the authorization decision, so deactivating a member locks
20
+ * them out instantly regardless of cookie age.
21
+ *
22
+ * Workspace scoping (ADR 014, user-scoped credential model): a session
23
+ * resolves to exactly ONE workspace per request via the shared
24
+ * resolveMembership rule — the X-Workspace-Id header names it (ACTIVE
25
+ * membership required, else null: fail closed, an unknown workspace and a
26
+ * workspace the user does not belong to are indistinguishable); without the
27
+ * header the user's default membership wins, else the deterministic oldest
28
+ * active membership.
29
+ *
30
+ * API-key and OAuth-bearer resolution live in the auth-context middleware
31
+ * (they are credential formats, not identity sources) and share the SAME
32
+ * selection rule; this provider is the seam the central account service
33
+ * replaces later.
34
+ */
35
+ export class LocalIdentityProvider implements IdentityProvider {
36
+ constructor(
37
+ private readonly auth: Auth,
38
+ private readonly db: Db,
39
+ private readonly hasGoogle: boolean,
40
+ private readonly hasOtp: boolean = false,
41
+ private readonly hasPasswordReset: boolean = false,
42
+ private readonly hasEmailChange: boolean = false,
43
+ /** Cloud only: one cached reconcile on a well-formed selector miss. */
44
+ private readonly onWorkspaceMiss?: OnWorkspaceMiss | undefined
45
+ ) {}
46
+
47
+ async resolve(ctx: RequestContext): Promise<Principal | null> {
48
+ const session = await this.auth.api.getSession({
49
+ headers: ctx.headers as Headers
50
+ });
51
+ if (!session?.user) return null;
52
+
53
+ const requested = ctx.headers.get(ACTIVE_WORKSPACE_HEADER)?.trim() || null;
54
+ let row = await resolveMembership(this.db, session.user.id, requested);
55
+ if (!row && requested && this.onWorkspaceMiss && isWorkspaceSelector(requested)) {
56
+ // Unknown-workspace deep-link retry (cloud): the named workspace may
57
+ // be a hub org granted since the last pass. One cached reconcile, one
58
+ // re-run of the SAME lookup — no recursion.
59
+ await this.onWorkspaceMiss(session.user.id, requested);
60
+ row = await resolveMembership(this.db, session.user.id, requested);
61
+ }
62
+ if (!row) return null;
63
+
64
+ return {
65
+ userId: session.user.id,
66
+ email: session.user.email,
67
+ name: session.user.name,
68
+ workspaceId: row.workspaceId,
69
+ role: row.role,
70
+ origin: row.origin,
71
+ via: 'session',
72
+ scopes: null,
73
+ ...(row.accountRef ? { accountRef: row.accountRef } : {})
74
+ };
75
+ }
76
+
77
+ describe(): InstanceAuthDescriptor {
78
+ // 'oauth' is always on: every instance is an OAuth 2.1 AS for its /mcp (M6).
79
+ const methods: InstanceAuthDescriptor['methods'] = ['password', 'api-key', 'oauth'];
80
+ if (this.hasOtp) methods.push('email-otp');
81
+ if (this.hasGoogle) methods.push('google');
82
+ return {
83
+ methods,
84
+ passwordReset: this.hasPasswordReset,
85
+ emailChange: this.hasEmailChange,
86
+ // Opt-in TOTP needs no email driver — always available on the template.
87
+ twoFactor: true
88
+ };
89
+ }
90
+ }
@@ -0,0 +1,28 @@
1
+ import type { EntitlementService, IdentityProvider, UsageSink } from '@antasphere/chassis-contract';
2
+ import type { EventBus } from './events.js';
3
+ import type { WorkspaceService } from './workspaces.js';
4
+
5
+ /**
6
+ * Boot-time module registry: the single place where seam implementations are
7
+ * bound. The template binds local defaults; a rail-connected or ee edition
8
+ * re-binds its own implementations here at boot (Cal.com/n8n pattern) and
9
+ * nothing else in the codebase changes.
10
+ */
11
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
12
+ export interface PlatformRegistry<TExtra = {}> {
13
+ identity: IdentityProvider;
14
+ entitlements: EntitlementService;
15
+ usage: UsageSink;
16
+ events: EventBus<TExtra>;
17
+ /**
18
+ * Workspace lifecycle (ADR 014). Setup creates the FIRST workspace through
19
+ * it; product flows that open workspace creation (the cloud edition's lazy
20
+ * org projection) call it here instead of inserting rows themselves.
21
+ */
22
+ workspaces: WorkspaceService;
23
+ }
24
+
25
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
26
+ export function createRegistry<TExtra = {}>(defaults: PlatformRegistry<TExtra>): PlatformRegistry<TExtra> {
27
+ return { ...defaults };
28
+ }
@@ -0,0 +1,13 @@
1
+ import type { UsageEvent, UsageSink } from '@antasphere/chassis-contract';
2
+
3
+ /**
4
+ * Default UsageSink: drop everything. Domain code always emits usage events
5
+ * (they double as local analytics hooks); only a rail-connected sink turns
6
+ * them into billing. Zero phone-home is the default posture — nothing leaves
7
+ * the instance unless an operator explicitly configures a sink.
8
+ */
9
+ export class NoopUsageSink implements UsageSink {
10
+ async emit(_event: UsageEvent): Promise<void> {
11
+ // intentionally empty
12
+ }
13
+ }
@@ -0,0 +1,41 @@
1
+ import { workspaceMembers, workspaces, type DbConn } from '@antasphere/chassis-db';
2
+
3
+ /**
4
+ * Workspace lifecycle — the template's one creation path (ADR 014). Setup
5
+ * creates the FIRST workspace through it; products that open their own
6
+ * workspace-creation flow (a hub's sign-up, a cloud edition's lazy org
7
+ * projection) call it via the platform registry instead of hand-rolling
8
+ * the two inserts. The template exposed no HTTP endpoint for this (workspace
9
+ * creation is a product decision); the chassis took that decision with
10
+ * `POST /workspaces` (api/workspaces.ts, PRDCT-2444): sessions only, capped
11
+ * per person, and still through THIS service — never a second insert path.
12
+ */
13
+ export class WorkspaceService {
14
+ constructor(private readonly db: DbConn) {}
15
+
16
+ /**
17
+ * Create a workspace with `ownerUserId` as its ACTIVE OWNER — one unit:
18
+ * pass a transaction handle (`conn`) to join an enclosing transaction
19
+ * (setup does), or omit it to run the two inserts on this service's
20
+ * connection inside their own transaction when it supports one.
21
+ */
22
+ async create(name: string, ownerUserId: string, conn: DbConn = this.db): Promise<{ workspaceId: string }> {
23
+ const run = async (tx: DbConn) => {
24
+ const [workspace] = await tx.insert(workspaces).values({ name }).returning({ id: workspaces.id });
25
+ if (!workspace) throw new Error('workspace insert returned no row');
26
+ await tx.insert(workspaceMembers).values({
27
+ workspaceId: workspace.id,
28
+ userId: ownerUserId,
29
+ role: 'owner'
30
+ });
31
+ return { workspaceId: workspace.id };
32
+ };
33
+ // A DbConn may already BE a transaction (no .transaction on the type);
34
+ // when the caller hands us a plain Db, wrap the pair so a workspace can
35
+ // never exist without its owner membership.
36
+ if ('transaction' in conn && typeof conn.transaction === 'function') {
37
+ return conn.transaction(async (tx) => run(tx));
38
+ }
39
+ return run(conn);
40
+ }
41
+ }
@@ -0,0 +1,160 @@
1
+ import { sql, type SQL, type SQLWrapper } from 'drizzle-orm';
2
+ import type { Principal, ProjectRole } from '@antasphere/chassis-contract';
3
+ import { projects, type DbConn } from '@antasphere/chassis-db';
4
+
5
+ /**
6
+ * THE project access rule, stated once. A tool links its own resources to
7
+ * projects through a table of its own, and asks ONE question of the chassis:
8
+ * "does this principal hold a grant of at least `<role>` on the project in
9
+ * this column?". The chassis routes (`api/projects.ts`) ask the same question
10
+ * through the same builder, so a tool cannot drift from them.
11
+ *
12
+ * What the predicate carries, and every clause is load-bearing:
13
+ *
14
+ * - **The guest refusal.** An `origin='guest'` membership exists for
15
+ * principal resolution only (D2): it is never a project member. Refused on
16
+ * the PRINCIPAL (`false`, no query at all) AND on the membership row the
17
+ * grant rides on (`origin <> 'guest'`), so a stray row is inert.
18
+ * - **The live membership.** The grant is read THROUGH its
19
+ * `workspace_members` row: same user, same workspace as the request,
20
+ * `is_active`. A deleted membership took the grant with it (the foreign
21
+ * key's cascade); a deactivated one resolves no principal at all.
22
+ * - **One workspace.** The project belongs to the request's workspace and to
23
+ * the membership's. A request never spans workspaces (ADR 014).
24
+ * - **The role ladder.** `manager` contains `editor` contains `viewer`.
25
+ * - **A team's grant (PRDCT-2794).** A person seated in a team that holds a
26
+ * place on the project holds the team's role, on the same live membership
27
+ * row; their effective role is the highest of their own grant and their
28
+ * teams'. A seat or a grant removed is felt on the next request.
29
+ * - **The operator view.** A workspace owner or admin acts as a manager on
30
+ * every project of the workspace (ADR 006), which is why a project with no
31
+ * manager stays manageable and there is no last-manager guard.
32
+ * - **The archived-write rule.** `access: 'write'` is off while the project
33
+ * is archived, for everyone, the operator included. A READ stays.
34
+ *
35
+ * Callers answer 404, never 403, when a READ predicate is false: a project a
36
+ * principal cannot read must not reveal its existence.
37
+ */
38
+
39
+ const LADDER: Record<ProjectRole, readonly ProjectRole[]> = {
40
+ viewer: ['viewer', 'editor', 'manager'],
41
+ editor: ['editor', 'manager'],
42
+ manager: ['manager']
43
+ };
44
+
45
+ export interface ProjectGrantOptions {
46
+ /** The least role that satisfies the predicate. */
47
+ atLeast: ProjectRole;
48
+ /** `write` adds the archived-write rule; `read` does not look at the archive. */
49
+ access: 'read' | 'write';
50
+ }
51
+
52
+ /**
53
+ * A boolean SQL expression over `projectId`, a column (or expression) of the
54
+ * CALLER's query that holds a project id: the tool's link table column, or
55
+ * `projects.id` itself. The aliases are prefixed so they cannot collide with
56
+ * the ones of the query the predicate is embedded in.
57
+ *
58
+ * **Pass a QUALIFIED reference when the predicate lands in a SELECT LIST.**
59
+ * drizzle renders a column object of a single-table select WITHOUT its table
60
+ * name there (`"id"`), and inside this subquery a bare `"id"` binds to the
61
+ * subquery's own tables: ambiguous at best, always-true at worst. A raw
62
+ * `sql\`"link_table"."project_id"\`` (or `PROJECTS_ID` below) is immune; a
63
+ * column object is safe in a WHERE, where drizzle always qualifies it.
64
+ */
65
+ export function projectGrantPredicate(
66
+ principal: Pick<Principal, 'userId' | 'workspaceId' | 'role' | 'origin'>,
67
+ projectId: SQLWrapper,
68
+ opts: ProjectGrantOptions
69
+ ): SQL {
70
+ if (principal.origin === 'guest') return sql`false`;
71
+ const live = opts.access === 'write' ? sql`AND prj_pr.archived_at IS NULL` : sql``;
72
+ if (principal.role === 'owner' || principal.role === 'admin') {
73
+ return sql`EXISTS (
74
+ SELECT 1 FROM projects prj_pr
75
+ WHERE prj_pr.id = ${projectId}
76
+ AND prj_pr.workspace_id = ${principal.workspaceId}
77
+ ${live}
78
+ )`;
79
+ }
80
+ const roles = sql.join(
81
+ LADDER[opts.atLeast].map((role) => sql`${role}`),
82
+ sql`, `
83
+ );
84
+ // Two ways to hold a grant, judged on the SAME live membership row: the
85
+ // person's own entry (`project_members`), or the entry of a team the person
86
+ // is seated in (`project_teams` through `workspace_team_members`, PRDCT-2794).
87
+ // The team's workspace is checked against the membership's like the
88
+ // project's, so a seat can never reach across workspaces; the effective
89
+ // role is the highest of the two, which the ladder's IN list yields.
90
+ return sql`EXISTS (
91
+ SELECT 1
92
+ FROM workspace_members prj_wm
93
+ JOIN projects prj_pr ON prj_pr.workspace_id = prj_wm.workspace_id
94
+ WHERE prj_pr.id = ${projectId}
95
+ AND prj_wm.user_id = ${principal.userId}
96
+ AND prj_wm.workspace_id = ${principal.workspaceId}
97
+ AND prj_wm.is_active
98
+ AND prj_wm.origin <> 'guest'
99
+ ${live}
100
+ AND (
101
+ EXISTS (
102
+ SELECT 1 FROM project_members prj_pm
103
+ WHERE prj_pm.project_id = prj_pr.id
104
+ AND prj_pm.member_id = prj_wm.id
105
+ AND prj_pm.role IN (${roles})
106
+ )
107
+ OR EXISTS (
108
+ SELECT 1
109
+ FROM project_teams prj_pt
110
+ JOIN workspace_team_members prj_tm ON prj_tm.team_id = prj_pt.team_id
111
+ JOIN workspace_teams prj_t ON prj_t.id = prj_pt.team_id
112
+ WHERE prj_pt.project_id = prj_pr.id
113
+ AND prj_tm.member_id = prj_wm.id
114
+ AND prj_t.workspace_id = prj_wm.workspace_id
115
+ AND prj_pt.role IN (${roles})
116
+ )
117
+ )
118
+ )`;
119
+ }
120
+
121
+ /** `projects.id`, always qualified: safe in a select list as in a WHERE (see above). */
122
+ export const PROJECTS_ID: SQL = sql.raw('"projects"."id"');
123
+
124
+ /**
125
+ * The caller's effective role on a project AS A SQL EXPRESSION over a project
126
+ * id column: `manager`, `editor`, `viewer`, or NULL (no read). Built from the
127
+ * predicate above, never beside it. Archive-blind on purpose: a role is a
128
+ * READ fact, and whether an act is allowed on an archived project is the
129
+ * act's own question (`access: 'write'`, or the route's 409).
130
+ */
131
+ export function projectRoleExpression(
132
+ principal: Pick<Principal, 'userId' | 'workspaceId' | 'role' | 'origin'>,
133
+ projectId: SQLWrapper
134
+ ): SQL<ProjectRole | null> {
135
+ const has = (atLeast: ProjectRole) =>
136
+ projectGrantPredicate(principal, projectId, { atLeast, access: 'read' });
137
+ return sql<ProjectRole | null>`CASE
138
+ WHEN ${has('manager')} THEN 'manager'
139
+ WHEN ${has('editor')} THEN 'editor'
140
+ WHEN ${has('viewer')} THEN 'viewer'
141
+ END`;
142
+ }
143
+
144
+ /**
145
+ * The effective role of `principal` on one project of the request's
146
+ * workspace, or null. **null = 404**: no such project here, or a project the
147
+ * principal cannot read; the two must stay indistinguishable to the caller.
148
+ */
149
+ export async function projectRole(
150
+ conn: DbConn,
151
+ principal: Pick<Principal, 'userId' | 'workspaceId' | 'role' | 'origin'>,
152
+ projectId: string
153
+ ): Promise<ProjectRole | null> {
154
+ const rows = await conn
155
+ .select({ role: projectRoleExpression(principal, PROJECTS_ID) })
156
+ .from(projects)
157
+ .where(sql`${projects.id} = ${projectId} AND ${projects.workspaceId} = ${principal.workspaceId}`)
158
+ .limit(1);
159
+ return rows[0]?.role ?? null;
160
+ }
@@ -0,0 +1,7 @@
1
+ export {
2
+ PROJECTS_ID,
3
+ projectGrantPredicate,
4
+ projectRole,
5
+ projectRoleExpression,
6
+ type ProjectGrantOptions
7
+ } from './access.js';
@@ -0,0 +1,29 @@
1
+ import type { Context } from 'hono';
2
+
3
+ /**
4
+ * The low-cardinality, secret-free label for a request, used by BOTH the
5
+ * completion log line and the trace span.
6
+ *
7
+ * The raw `c.req.path` must never reach the log stream or a span attribute.
8
+ * Path segments are request data like any other: the moment a route puts a
9
+ * capability in the URL — a share secret, a one-time token, an invitation
10
+ * code — every log sink, every trace backend, and every operator with
11
+ * `docker logs` holds a working credential, and the redaction list cannot
12
+ * help (it keys off object properties, and `path` is one opaque string).
13
+ * Logging the MATCHED ROUTE PATTERN instead (`/v/:secret`, not
14
+ * `/v/9f3c…`) keeps the line just as useful for debugging and cardinality
15
+ * bounded, and it is secret-free by construction for every route that will
16
+ * ever be added.
17
+ *
18
+ * `routePath` is only populated once routing has run, so callers must read
19
+ * this AFTER `await next()`. Unmatched requests have no pattern to report:
20
+ * they get the literal `(unmatched)` rather than the attacker-controlled URL
21
+ * they probed with.
22
+ */
23
+ export function routeLabel(c: Context): string {
24
+ const matched = c.req.routePath;
25
+ // Hono answers '/*' for a catch-all match and for no match at all; neither
26
+ // says anything the pattern doesn't, and both are safe to report as-is.
27
+ if (!matched) return '(unmatched)';
28
+ return matched;
29
+ }
@@ -0,0 +1,79 @@
1
+ import { Hono } from 'hono';
2
+ import type { RuntimeState } from '../state.js';
3
+
4
+ /**
5
+ * /healthz — liveness. No dependencies: answers 200 whenever the event loop
6
+ * runs, so orchestrators never restart a replica that is merely waiting on
7
+ * the database.
8
+ *
9
+ * /readyz — readiness. 503 until env is parsed, migrations are applied (or
10
+ * confirmed current), and the DB is reachable; 503 again while draining; and
11
+ * 503 whenever the backing store stops being writable.
12
+ *
13
+ * That last clause is the whole point of `probeStorage`. Readiness used to be
14
+ * a boot-time boolean, so the storage probe ran exactly once, at startup: an
15
+ * instance whose /data volume was emptied, unmounted or turned read-only
16
+ * after boot — the state a failed restore leaves behind — kept answering 200
17
+ * and kept taking traffic it could not serve. Readiness has to be a live
18
+ * claim about the dependencies, not a memory of them.
19
+ */
20
+ export interface HealthDeps {
21
+ /** Re-probe the backing store. Must throw when it is not writable. */
22
+ probeStorage?: () => Promise<void>;
23
+ /** How long a SUCCESSFUL probe is trusted before it re-runs. */
24
+ storageProbeTtlMs?: number;
25
+ /** Called with the probe failure so it lands in the logs. */
26
+ onStorageFailure?: (err: unknown) => void;
27
+ /** Injectable clock (tests). */
28
+ now?: () => number;
29
+ }
30
+
31
+ /**
32
+ * Successes are cached briefly so a fast readiness poll does not become a
33
+ * PUT+DELETE per second against S3. Failures are NEVER cached: the next
34
+ * request re-probes, so recovery is observed immediately.
35
+ */
36
+ const DEFAULT_STORAGE_PROBE_TTL_MS = 10_000;
37
+
38
+ export function healthRoutes(state: RuntimeState, deps: HealthDeps = {}): Hono {
39
+ const app = new Hono();
40
+ const { probeStorage, onStorageFailure } = deps;
41
+ const ttlMs = deps.storageProbeTtlMs ?? DEFAULT_STORAGE_PROBE_TTL_MS;
42
+ const now = deps.now ?? (() => Date.now());
43
+
44
+ let trustedUntil = 0;
45
+ let inflight: Promise<unknown> | null = null;
46
+
47
+ /** Resolves to the failure, or null when storage is reachable. */
48
+ function checkStorage(): Promise<unknown> {
49
+ if (!probeStorage) return Promise.resolve(null);
50
+ if (now() < trustedUntil) return Promise.resolve(null);
51
+ // One probe at a time: a burst of readiness polls must not fan out into a
52
+ // burst of writes against the store.
53
+ const pending = (inflight ??= (async () => {
54
+ try {
55
+ await probeStorage();
56
+ trustedUntil = now() + ttlMs;
57
+ return null;
58
+ } catch (err) {
59
+ trustedUntil = 0;
60
+ onStorageFailure?.(err);
61
+ return err ?? new Error('storage probe failed');
62
+ } finally {
63
+ inflight = null;
64
+ }
65
+ })());
66
+ return pending;
67
+ }
68
+
69
+ app.get('/healthz', (c) => c.json({ status: 'ok' }));
70
+ app.get('/readyz', async (c) => {
71
+ if (state.draining) return c.json({ status: 'unavailable', reason: 'draining' }, 503);
72
+ if (!state.ready) return c.json({ status: 'unavailable', reason: state.reason }, 503);
73
+ // The reason stays coarse on purpose: /readyz is unauthenticated and a
74
+ // driver's error text carries bucket names and filesystem paths.
75
+ if (await checkStorage()) return c.json({ status: 'unavailable', reason: 'storage' }, 503);
76
+ return c.json({ status: 'ready' });
77
+ });
78
+ return app;
79
+ }
@@ -0,0 +1,2 @@
1
+ export { healthRoutes } from './health.js';
2
+ export { wellKnownRoutes } from './wellknown.js';
@@ -0,0 +1,67 @@
1
+ import { Hono, type Context } from 'hono';
2
+ import {
3
+ oauthProviderAuthServerMetadata,
4
+ oauthProviderOpenIdConfigMetadata
5
+ } from '@better-auth/oauth-provider';
6
+ import { mcpResourceUrl, type Auth } from '../identity/better-auth.js';
7
+
8
+ /**
9
+ * Root-level OAuth discovery surface.
10
+ *
11
+ * The oauthProvider plugin serves RFC 8414 / OIDC discovery under the
12
+ * /api/v1/auth base path, but clients resolve discovery from the ISSUER (the
13
+ * bare origin — jwt.issuer in identity/better-auth.ts), so the same documents
14
+ * must exist at the origin root. RFC 9728 protected-resource metadata is ours:
15
+ * it points the 401-challenged MCP client at this same origin as its
16
+ * authorization server. All documents are public by design and fetched
17
+ * cross-origin by browser-based MCP hosts — wide-open CORS is correct.
18
+ */
19
+ const CORS_HEADERS = {
20
+ 'Access-Control-Allow-Origin': '*',
21
+ 'Access-Control-Allow-Methods': 'GET, OPTIONS',
22
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, mcp-protocol-version',
23
+ 'Access-Control-Max-Age': '86400'
24
+ } as const;
25
+
26
+ export interface WellKnownDeps {
27
+ auth: Auth;
28
+ publicBaseUrl: string;
29
+ instanceName?: string;
30
+ /** The tool's OAuth scope list, as registered with the provider: what `scopes_supported` advertises. */
31
+ oauthScopes: readonly string[];
32
+ }
33
+
34
+ export function wellKnownRoutes({ auth, publicBaseUrl, oauthScopes }: WellKnownDeps): Hono {
35
+ const app = new Hono();
36
+
37
+ const asMetadata = oauthProviderAuthServerMetadata(auth, {
38
+ headers: { ...CORS_HEADERS, 'Cache-Control': 'public, max-age=3600' }
39
+ });
40
+ const oidcMetadata = oauthProviderOpenIdConfigMetadata(auth, {
41
+ headers: { ...CORS_HEADERS, 'Cache-Control': 'public, max-age=3600' }
42
+ });
43
+
44
+ app.get('/.well-known/oauth-authorization-server', (c) => asMetadata(c.req.raw));
45
+ app.get('/.well-known/openid-configuration', (c) => oidcMetadata(c.req.raw));
46
+
47
+ // RFC 9728: served at the origin level AND at the path-aware derivation
48
+ // (clients insert /.well-known/oauth-protected-resource between origin and
49
+ // the resource path /mcp) — both return the same document.
50
+ const protectedResource = (c: Context) =>
51
+ c.json(
52
+ {
53
+ resource: mcpResourceUrl(publicBaseUrl),
54
+ authorization_servers: [publicBaseUrl],
55
+ scopes_supported: [...oauthScopes],
56
+ bearer_methods_supported: ['header']
57
+ },
58
+ 200,
59
+ { ...CORS_HEADERS, 'Cache-Control': 'public, max-age=3600' }
60
+ );
61
+ app.get('/.well-known/oauth-protected-resource', (c) => protectedResource(c));
62
+ app.get('/.well-known/oauth-protected-resource/mcp', (c) => protectedResource(c));
63
+
64
+ app.options('/.well-known/*', (c) => c.body(null, 204, { ...CORS_HEADERS }));
65
+
66
+ return app;
67
+ }