@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,61 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ /**
3
+ * Cross-site request forgery defence for the whole `/api/v1` surface.
4
+ *
5
+ * The session cookie authenticates every business route (`/orgs`, `/members`,
6
+ * `/invitations`, `/me/*`, `/apikeys`, every product route a instantiation
7
+ * adds), and a cookie is attached by the browser on a cross-site POST just as
8
+ * happily as on a same-origin one. Better Auth's own origin check covers only
9
+ * its `/sign-in` paths, so without this middleware a page on any origin could
10
+ * drive a signed-in user's whole API.
11
+ *
12
+ * Two independent signals, both browser-set and unforgeable by page script
13
+ * (both are Forbidden Header Names — `fetch` cannot override them):
14
+ *
15
+ * 1. `Sec-Fetch-Site: cross-site` — a request initiated by a document on a
16
+ * different site. Refused outright.
17
+ * 2. `Origin` — present on every browser request with an unsafe method.
18
+ * Refused unless it is the origin we are being served on, the configured
19
+ * public origin, or an explicitly trusted extra.
20
+ *
21
+ * Deliberately NOT refused:
22
+ *
23
+ * - Safe methods (GET/HEAD/OPTIONS). A cross-site read cannot be seen by the
24
+ * attacker — `/api/v1` sends no `Access-Control-Allow-Origin` except on the
25
+ * OAuth surfaces below — and refusing them would break legitimate
26
+ * cross-origin embeds of authenticated content.
27
+ * - Requests presenting an `Authorization` header. Those are API keys and
28
+ * OAuth bearers: not ambient credentials, so not forgeable cross-site (a
29
+ * page cannot attach the header without a preflight we never approve).
30
+ * Refusing them would break every scripted and browser-based MCP client.
31
+ * - The deliberate wildcard-CORS OAuth endpoints (oauth-public.ts): token,
32
+ * register, introspect, revoke, jwks and discovery are cookie-less by
33
+ * design and MUST answer any origin.
34
+ * - Requests with neither header. Non-browser clients (curl, the CLI, the
35
+ * SDK, server-to-server) send neither, and this middleware must not become
36
+ * a browser-only gate on a self-hosted API. The ambient-credential threat
37
+ * this closes is browser-only, and browsers always send at least one.
38
+ */
39
+ export interface CrossSiteGuardOptions {
40
+ /** The instance's configured public origin (PUBLIC_BASE_URL). */
41
+ publicBaseUrl: string;
42
+ /**
43
+ * Additional origins allowed to drive the API with cookies — a separately
44
+ * hosted first-party dashboard, say. Empty on the template.
45
+ */
46
+ extraTrustedOrigins?: readonly string[];
47
+ /**
48
+ * Origins REFUSED even when they equal the origin this request was served
49
+ * on: the viewer origin (VIEWER_BASE_URL, PRDCT-1352). The host gate keeps
50
+ * `/api/v1` (minus the token-authed `/viewer/*` subset) off that hostname
51
+ * altogether, so in the shipped assembly no request here carries it as the
52
+ * serving origin — this is the second lock, so that a gate regression or a
53
+ * proxy routing the viewer hostname at the app never turns "the origin we
54
+ * are served on" into a trust grant for author-controlled script.
55
+ */
56
+ deniedOrigins?: readonly string[];
57
+ /** Escape hatch for surfaces that must stay open (paths are `/api/v1/...`). */
58
+ isExempt?: (path: string) => boolean;
59
+ }
60
+ export declare function crossSiteGuard({ publicBaseUrl, extraTrustedOrigins, deniedOrigins, isExempt }: CrossSiteGuardOptions): MiddlewareHandler;
61
+ //# sourceMappingURL=cross-site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-site.d.ts","sourceRoot":"","sources":["../../src/middleware/cross-site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAIvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACtC;AAiBD,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,mBAAwB,EACxB,aAAkB,EAClB,QAAQ,EACT,EAAE,qBAAqB,GAAG,iBAAiB,CAsC3C"}
@@ -0,0 +1,59 @@
1
+ import { apiError } from '../api/errors.js';
2
+ import { isPublicOauthPath } from './oauth-public.js';
3
+ const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
4
+ function originOf(value) {
5
+ try {
6
+ return new URL(value).origin;
7
+ }
8
+ catch {
9
+ return null;
10
+ }
11
+ }
12
+ /** The origin this very request was addressed to (works on localhost, previews, any domain). */
13
+ function servingOrigin(c) {
14
+ return originOf(c.req.url);
15
+ }
16
+ export function crossSiteGuard({ publicBaseUrl, extraTrustedOrigins = [], deniedOrigins = [], isExempt }) {
17
+ const configured = new Set();
18
+ const publicOrigin = originOf(publicBaseUrl);
19
+ if (publicOrigin)
20
+ configured.add(publicOrigin);
21
+ for (const extra of extraTrustedOrigins) {
22
+ const origin = originOf(extra);
23
+ if (origin)
24
+ configured.add(origin);
25
+ }
26
+ const denied = new Set();
27
+ for (const value of deniedOrigins) {
28
+ const origin = originOf(value);
29
+ if (origin)
30
+ denied.add(origin);
31
+ }
32
+ // A denied origin wins over every trust source, the serving origin included.
33
+ for (const origin of denied)
34
+ configured.delete(origin);
35
+ return async (c, next) => {
36
+ if (SAFE_METHODS.has(c.req.method))
37
+ return next();
38
+ if (c.req.header('authorization'))
39
+ return next();
40
+ if (isPublicOauthPath(c.req.path))
41
+ return next();
42
+ if (isExempt?.(c.req.path))
43
+ return next();
44
+ const secFetchSite = c.req.header('sec-fetch-site');
45
+ if (secFetchSite === 'cross-site') {
46
+ return apiError(c, 403, 'cross_site_forbidden', 'Cross-site requests are not accepted on this API');
47
+ }
48
+ const origin = c.req.header('origin');
49
+ if (origin) {
50
+ const serving = servingOrigin(c);
51
+ const trusted = !denied.has(origin) && (origin === serving || configured.has(origin));
52
+ if (!trusted) {
53
+ return apiError(c, 403, 'cross_site_forbidden', 'Cross-site requests are not accepted on this API');
54
+ }
55
+ }
56
+ return next();
57
+ };
58
+ }
59
+ //# sourceMappingURL=cross-site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-site.js","sourceRoot":"","sources":["../../src/middleware/cross-site.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ /**
3
+ * P7 (internal/federation.md "Hub-managed membership"): on the cloud edition,
4
+ * membership of a HUB-ORIGIN (projected) workspace is the hub's source of
5
+ * truth — invites, roles, and removals happen at the hub and flow in via
6
+ * SSO login + the P4 re-assertion. A local membership mutation on such a
7
+ * workspace would create divergence the next login/re-assertion fights, so
8
+ * every mutation on the local /members + /invitations surfaces answers this
9
+ * refusal instead. READS stay open: the projected roster is real.
10
+ *
11
+ * Why 403 (not 410): the member rows demonstrably exist (GET /members
12
+ * serves them), so "the resource is gone" would be false — what is denied
13
+ * is the OPERATION's local authority, for every caller, regardless of role
14
+ * or credential. That is RFC 9110 403's "forbidden for reasons unrelated to
15
+ * the credentials", and it keeps the platform's refusal vocabulary in one
16
+ * register (guest_forbidden, endpoint_not_allowed, workspace_mismatch are
17
+ * all 403). The `hub_managed` code + `details.manageUrl` carry the pointer.
18
+ *
19
+ * Fail-closed by construction:
20
+ * - Hub-origin detection keys on `principal.accountRef`, which every
21
+ * credential resolver (session: platform/local-identity.ts; API key:
22
+ * apikeys/service.ts; OAuth bearer: identity/oauth-jwt.ts) populates from
23
+ * a LIVE join on `workspaces.central_account_id` for the request's ONE
24
+ * workspace (ADR 014) — the same signal the live hub gate keys on
25
+ * (identity/hub-live-gate.ts). There is no principal-construction path
26
+ * that skips the join.
27
+ * - The gate is method-keyed, not route-enumerated, and mounted ONCE per
28
+ * subtree wildcard (`/members/*`, `/invitations/*` — in Hono the
29
+ * wildcard also matches the collection root): any FUTURE mutation
30
+ * registered anywhere under those surfaces is refused by default, with
31
+ * no per-path registration to remember.
32
+ * - It is registered only on EDITION=cloud (the `hubConfig` presence
33
+ * switch, like every cloud seam) — oss carries zero behavior change, and
34
+ * on oss `centralAccountId` is never set anyway (double cover).
35
+ *
36
+ * Principal-less requests pass through untouched: the public invitation
37
+ * accept/lookup segments are explicitly SKIPPED where this is mounted (their
38
+ * target workspace is the invitation's, not the caller's — the accept
39
+ * handler runs its own hub-origin check on the invitation's workspace), and
40
+ * every other gated route 401s in its requireAuth/requireRole gate.
41
+ */
42
+ export declare function hubManagedMembershipGate(manageUrl: string, message?: string): MiddlewareHandler;
43
+ /** The teams' sentence for the same gate (PRDCT-2813): a projected team is shaped on the account site. */
44
+ export declare const HUB_MANAGED_TEAMS_MESSAGE = "Teams of this workspace are managed at the Antasphere hub \u2014 create, rename, and seat people there";
45
+ //# sourceMappingURL=hub-managed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-managed.d.ts","sourceRoot":"","sources":["../../src/middleware/hub-managed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAG9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,SAA2G,GACjH,iBAAiB,CAUnB;AAED,0GAA0G;AAC1G,eAAO,MAAM,yBAAyB,2GAC+D,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { apiError } from '../api/errors.js';
2
+ /**
3
+ * P7 (internal/federation.md "Hub-managed membership"): on the cloud edition,
4
+ * membership of a HUB-ORIGIN (projected) workspace is the hub's source of
5
+ * truth — invites, roles, and removals happen at the hub and flow in via
6
+ * SSO login + the P4 re-assertion. A local membership mutation on such a
7
+ * workspace would create divergence the next login/re-assertion fights, so
8
+ * every mutation on the local /members + /invitations surfaces answers this
9
+ * refusal instead. READS stay open: the projected roster is real.
10
+ *
11
+ * Why 403 (not 410): the member rows demonstrably exist (GET /members
12
+ * serves them), so "the resource is gone" would be false — what is denied
13
+ * is the OPERATION's local authority, for every caller, regardless of role
14
+ * or credential. That is RFC 9110 403's "forbidden for reasons unrelated to
15
+ * the credentials", and it keeps the platform's refusal vocabulary in one
16
+ * register (guest_forbidden, endpoint_not_allowed, workspace_mismatch are
17
+ * all 403). The `hub_managed` code + `details.manageUrl` carry the pointer.
18
+ *
19
+ * Fail-closed by construction:
20
+ * - Hub-origin detection keys on `principal.accountRef`, which every
21
+ * credential resolver (session: platform/local-identity.ts; API key:
22
+ * apikeys/service.ts; OAuth bearer: identity/oauth-jwt.ts) populates from
23
+ * a LIVE join on `workspaces.central_account_id` for the request's ONE
24
+ * workspace (ADR 014) — the same signal the live hub gate keys on
25
+ * (identity/hub-live-gate.ts). There is no principal-construction path
26
+ * that skips the join.
27
+ * - The gate is method-keyed, not route-enumerated, and mounted ONCE per
28
+ * subtree wildcard (`/members/*`, `/invitations/*` — in Hono the
29
+ * wildcard also matches the collection root): any FUTURE mutation
30
+ * registered anywhere under those surfaces is refused by default, with
31
+ * no per-path registration to remember.
32
+ * - It is registered only on EDITION=cloud (the `hubConfig` presence
33
+ * switch, like every cloud seam) — oss carries zero behavior change, and
34
+ * on oss `centralAccountId` is never set anyway (double cover).
35
+ *
36
+ * Principal-less requests pass through untouched: the public invitation
37
+ * accept/lookup segments are explicitly SKIPPED where this is mounted (their
38
+ * target workspace is the invitation's, not the caller's — the accept
39
+ * handler runs its own hub-origin check on the invitation's workspace), and
40
+ * every other gated route 401s in its requireAuth/requireRole gate.
41
+ */
42
+ export function hubManagedMembershipGate(manageUrl, message = 'Membership of this workspace is managed at the Antasphere hub — invite, remove, and change roles there') {
43
+ return async (c, next) => {
44
+ const method = c.req.method;
45
+ if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS')
46
+ return next();
47
+ const principal = c.get('principal');
48
+ if (principal?.accountRef) {
49
+ return apiError(c, 403, 'hub_managed', message, { manageUrl });
50
+ }
51
+ return next();
52
+ };
53
+ }
54
+ /** The teams' sentence for the same gate (PRDCT-2813): a projected team is shaped on the account site. */
55
+ export const HUB_MANAGED_TEAMS_MESSAGE = 'Teams of this workspace are managed at the Antasphere hub — create, rename, and seat people there';
56
+ //# sourceMappingURL=hub-managed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-managed.js","sourceRoot":"","sources":["../../src/middleware/hub-managed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,wBAAwB,CACtC,SAAiB,EACjB,OAAO,GAAG,wGAAwG;IAElH,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QAC5B,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,EAAE,CAAC;QACjF,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,SAAS,EAAE,UAAU,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED,0GAA0G;AAC1G,MAAM,CAAC,MAAM,yBAAyB,GACpC,mGAAmG,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ import { type Db } from '@antasphere/chassis-db';
3
+ /** Encrypt a response body for storage at rest: `iv.ciphertext.tag` base64url. */
4
+ export declare function seal(plain: string, authSecret: string): string;
5
+ /** Decrypt a sealed body; null on tamper, malformed input, or a wrong/rotated key. */
6
+ export declare function open(sealed: string, authSecret: string): string | null;
7
+ export interface IdempotencyDeps {
8
+ db: Db;
9
+ authSecret: string;
10
+ /** The tool's own create POSTs that take the claim (a pure predicate over the path; POST only). */
11
+ toolTargets?: (path: string) => boolean;
12
+ }
13
+ export declare function idempotency({ db, authSecret, toolTargets }: IdempotencyDeps): MiddlewareHandler;
14
+ //# sourceMappingURL=idempotency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAG9C,OAAO,EAAmB,KAAK,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAkGlE,kFAAkF;AAClF,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,sFAAsF;AACtF,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtE;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,EAAE,CAAC;IACP,UAAU,EAAE,MAAM,CAAC;IACnB,mGAAmG;IACnG,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,eAAe,GAAG,iBAAiB,CAmI/F"}
@@ -0,0 +1,222 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
2
+ import { and, eq } from 'drizzle-orm';
3
+ import { idempotencyKeys } from '@antasphere/chassis-db';
4
+ import { apiError } from '../api/errors.js';
5
+ /**
6
+ * Idempotency-Key middleware: an opt-in `Idempotency-Key` request header on
7
+ * the non-idempotent create POSTs makes a network-blip retry replay the
8
+ * original response instead of double-creating. Claim-first: the row is
9
+ * inserted BEFORE the handler runs (the unique index is the mutex), so two
10
+ * concurrent requests with the same key can never both execute.
11
+ *
12
+ * Explicit target list, fail-closed style — only these consult it (the
13
+ * lines that say "the tool's" are the TOOL's, declared through `toolTargets`):
14
+ * POST /api/v1/api-keys
15
+ * POST /api/v1/invitations
16
+ * POST /api/v1/members/{id}/reset-link
17
+ * POST /api/v1/members/{id}/change-email-link (FUZZ-7, PRDCT-1354: the
18
+ * SECOND secret-minting member route, and the more dangerous one — its
19
+ * token is sign-in-equivalent. Its contract has always declared
20
+ * `Idempotency-Key` and a 409, but the claim never covered it, so a
21
+ * retried mint silently produced a SECOND live sign-in-equivalent JWT
22
+ * that cannot be revoked, on top of the first. The two mint routes must
23
+ * stay listed together.)
24
+ * the tool's token mint on one of its resources
25
+ * the tool's duplicate of a resource (PRDCT-2279: one click mints
26
+ * one copy; a network-blip retry must not mint a second copy)
27
+ * POST /api/v1/workspaces (PRDCT-2444/2443: one click mints one workspace;
28
+ * on cloud the retry would otherwise create a second organization at
29
+ * the hub. The claim is scoped to the caller's CURRENT workspace + user;
30
+ * the cloud zero-membership session has no principal and runs unclaimed)
31
+ * the tool's upload reserve (a retried reserve must not leak a
32
+ * second session + reserved resource id)
33
+ * POST /api/v1/projects (one click mints one project) and
34
+ * POST /api/v1/projects/{id}/members (a retried add answers the first
35
+ * add's 201, not 409 `already_member`)
36
+ * Deliberate NON-targets:
37
+ * POST /api/v1/files and the tool's asset upload — content-addressed
38
+ * dedupe already makes them idempotent, and upload bodies must never be
39
+ * buffered here;
40
+ * POST /api/v1/setup and /api/v1/invitations/accept — one-shot by
41
+ * construction (retries answer 410), and they run without a principal;
42
+ * the tool's version commits — one-shot (session consumed / version counter)
43
+ * by construction: a retry answers 409.
44
+ *
45
+ * The cached response body is stored AES-256-GCM ENCRYPTED: these responses
46
+ * carry one-shot secrets (the full API key, the invitation acceptUrl token,
47
+ * the reset link) whose plaintext is deliberately never persisted anywhere
48
+ * else, and this cache must not become the exception. Sealed payload format:
49
+ * `iv.ciphertext.tag`, each part base64url; key = sha256(authSecret +
50
+ * ':idempotency'). Rotating AUTH_SECRET inside the 24h window is the same
51
+ * hard cutover it is for API keys: `open()` fails closed (null) and the
52
+ * stale row is dropped and re-executed.
53
+ *
54
+ * Accepted edge: a crash between the handler's commit and the response
55
+ * persist leaves a claim without a response — same-key retries answer 409
56
+ * `idempotency_in_flight` until the 24h expiry. Safe (never double-creates),
57
+ * mildly annoying, self-healing.
58
+ */
59
+ /** Rows live 24h (the Stripe convention); the nightly purge deletes expired ones. */
60
+ const TTL_MS = 24 * 60 * 60 * 1000;
61
+ const KEY_MAX_LENGTH = 200;
62
+ const TARGET_PATHS = new Set([
63
+ '/api/v1/api-keys',
64
+ '/api/v1/invitations',
65
+ '/api/v1/workspaces',
66
+ '/api/v1/projects'
67
+ ]);
68
+ // The two member routes that MINT a credential for another user. Both are
69
+ // covered (FUZZ-7): a replayed mint hands out a second live secret, and the
70
+ // change-email JWT is stateless, so it cannot even be revoked afterwards.
71
+ const RESET_LINK_RE = /^\/api\/v1\/members\/[^/]+\/reset-link$/;
72
+ const CHANGE_EMAIL_LINK_RE = /^\/api\/v1\/members\/[^/]+\/change-email-link$/;
73
+ const PROJECT_MEMBERS_RE = /^\/api\/v1\/projects\/[^/]+\/members$/;
74
+ function isTarget(method, path, toolTargets) {
75
+ return (method === 'POST' &&
76
+ (TARGET_PATHS.has(path) ||
77
+ RESET_LINK_RE.test(path) ||
78
+ CHANGE_EMAIL_LINK_RE.test(path) ||
79
+ PROJECT_MEMBERS_RE.test(path) ||
80
+ (toolTargets?.(path) ?? false)));
81
+ }
82
+ /** AES-256-GCM key derived from the server auth secret (domain-separated). */
83
+ function keyOf(authSecret) {
84
+ return createHash('sha256')
85
+ .update(authSecret + ':idempotency')
86
+ .digest();
87
+ }
88
+ /** Encrypt a response body for storage at rest: `iv.ciphertext.tag` base64url. */
89
+ export function seal(plain, authSecret) {
90
+ const iv = randomBytes(12);
91
+ const cipher = createCipheriv('aes-256-gcm', keyOf(authSecret), iv);
92
+ const ciphertext = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]);
93
+ return `${iv.toString('base64url')}.${ciphertext.toString('base64url')}.${cipher.getAuthTag().toString('base64url')}`;
94
+ }
95
+ /** Decrypt a sealed body; null on tamper, malformed input, or a wrong/rotated key. */
96
+ export function open(sealed, authSecret) {
97
+ const [iv, ciphertext, tag] = sealed.split('.');
98
+ if (!iv || !ciphertext || !tag)
99
+ return null;
100
+ try {
101
+ const decipher = createDecipheriv('aes-256-gcm', keyOf(authSecret), Buffer.from(iv, 'base64url'));
102
+ decipher.setAuthTag(Buffer.from(tag, 'base64url'));
103
+ return Buffer.concat([decipher.update(Buffer.from(ciphertext, 'base64url')), decipher.final()]).toString('utf8');
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ export function idempotency({ db, authSecret, toolTargets }) {
110
+ return async (c, next) => {
111
+ if (!isTarget(c.req.method, c.req.path, toolTargets))
112
+ return next();
113
+ const key = c.req.header('idempotency-key');
114
+ if (key === undefined)
115
+ return next();
116
+ if (key.length === 0 || key.length > KEY_MAX_LENGTH) {
117
+ // This middleware runs before contract validation, so the header bound
118
+ // is enforced here (the contract mirrors it for the OpenAPI document).
119
+ return apiError(c, 400, 'invalid_idempotency_key', 'Idempotency-Key must be 1–200 characters');
120
+ }
121
+ const principal = c.get('principal');
122
+ if (!principal)
123
+ return next(); // the route gates 401 downstream
124
+ // Hono caches the body: the zod validator's later c.req.json() re-reads
125
+ // from the same cache (verified on hono 4.12), so this text() is safe.
126
+ const bodyText = await c.req.text();
127
+ // Raw bytes, no canonicalization: a retry that re-serializes the same
128
+ // JSON differently hashes differently and 409s — by design.
129
+ const requestHash = createHash('sha256')
130
+ .update(`${c.req.method}\n${c.req.path}\n${bodyText}`)
131
+ .digest('hex');
132
+ const scope = and(eq(idempotencyKeys.workspaceId, principal.workspaceId), eq(idempotencyKeys.userId, principal.userId), eq(idempotencyKeys.key, key));
133
+ const claim = async () => {
134
+ const rows = await db
135
+ .insert(idempotencyKeys)
136
+ .values({
137
+ workspaceId: principal.workspaceId,
138
+ userId: principal.userId,
139
+ key,
140
+ requestHash,
141
+ expiresAt: new Date(Date.now() + TTL_MS)
142
+ })
143
+ .onConflictDoNothing({
144
+ target: [idempotencyKeys.workspaceId, idempotencyKeys.userId, idempotencyKeys.key]
145
+ })
146
+ .returning({ id: idempotencyKeys.id });
147
+ return rows[0]?.id ?? null;
148
+ };
149
+ let claimId = await claim();
150
+ if (claimId === null) {
151
+ // Claim lost: someone (possibly an earlier attempt of this very
152
+ // client) holds the key. Inspect the row to replay or conflict.
153
+ const [existing] = await db.select().from(idempotencyKeys).where(scope).limit(1);
154
+ if (!existing) {
155
+ // The row vanished between insert and select (raced the nightly
156
+ // purge). Claim once more; losing again means a live concurrent racer.
157
+ claimId = await claim();
158
+ if (claimId === null) {
159
+ return apiError(c, 409, 'idempotency_in_flight', 'A request with this Idempotency-Key is in flight — retry shortly');
160
+ }
161
+ }
162
+ else if (existing.requestHash !== requestHash) {
163
+ return apiError(c, 409, 'idempotency_key_reuse', 'This Idempotency-Key was already used with a different request');
164
+ }
165
+ else if (existing.responseStatus === null || existing.responseBodyEnc === null) {
166
+ return apiError(c, 409, 'idempotency_in_flight', 'The original request is still in flight — retry shortly');
167
+ }
168
+ else {
169
+ const plain = open(existing.responseBodyEnc, authSecret);
170
+ if (plain === null) {
171
+ // Sealed under a rotated AUTH_SECRET (documented hard cutover):
172
+ // unrecoverable, so drop the stale row and execute afresh.
173
+ await db.delete(idempotencyKeys).where(eq(idempotencyKeys.id, existing.id));
174
+ claimId = await claim();
175
+ if (claimId === null) {
176
+ return apiError(c, 409, 'idempotency_in_flight', 'A request with this Idempotency-Key is in flight — retry shortly');
177
+ }
178
+ }
179
+ else {
180
+ c.header('idempotency-replayed', 'true');
181
+ return c.json(JSON.parse(plain), existing.responseStatus);
182
+ }
183
+ }
184
+ }
185
+ // Owner path: we hold the claim; the handler executes.
186
+ const ownedClaimId = claimId;
187
+ // Best-effort release: a failed request must stay retryable with the
188
+ // same key (release errors must not mask the real outcome).
189
+ const release = async () => {
190
+ await db
191
+ .delete(idempotencyKeys)
192
+ .where(eq(idempotencyKeys.id, ownedClaimId))
193
+ .catch(() => { });
194
+ };
195
+ try {
196
+ await next();
197
+ }
198
+ catch (e) {
199
+ await release();
200
+ throw e;
201
+ }
202
+ if (c.res.status >= 200 && c.res.status < 300) {
203
+ // clone() tees the stream — the client still receives the original.
204
+ const body = await c.res.clone().text();
205
+ try {
206
+ await db
207
+ .update(idempotencyKeys)
208
+ .set({ responseStatus: c.res.status, responseBodyEnc: seal(body, authSecret) })
209
+ .where(eq(idempotencyKeys.id, ownedClaimId));
210
+ }
211
+ catch {
212
+ // Best-effort, like audit: the handler's mutation has already
213
+ // committed, so a failed persist must never turn into a 500. The
214
+ // claim stays response-less; same-key retries 409 until expiry.
215
+ }
216
+ }
217
+ else {
218
+ await release();
219
+ }
220
+ };
221
+ }
222
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/middleware/idempotency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export { type AdmitResult, type PrincipalGate, admitPrincipal, authContext, requireAuth, requireNonGuest, requireRole, resolveSessionPrincipal } from './auth-context.js';
2
+ export { type BucketDeclaration, type ClientIpFn, type QuotaDecision, type RateLimiters, type RequestQuotaService, createRateLimiters, createRequestQuota, emailKeyOf, makeClientIp, principalBucketKey, quotaHeaderEntries, rateLimit } from './rate-limit.js';
3
+ export { requestId } from './request-id.js';
4
+ export { type ScopeAllowlistOptions, type ScopeRule, createScopeAllowlist, looksLikeJwt } from './scopes.js';
5
+ export { authBodyGuard } from './auth-body.js';
6
+ export { crossSiteGuard } from './cross-site.js';
7
+ export { idempotency, open, seal } from './idempotency.js';
8
+ export { MAX_JSON_DEPTH, exceedsJsonDepth, jsonDepthLimit } from './json-depth.js';
9
+ export { noStoreAuthenticated } from './no-store.js';
10
+ export { isPublicOauthPath, oauthPublicEndpoints } from './oauth-public.js';
11
+ export { buildCsp, hstsValue, inlineScriptHashes, securityHeaders } from './security-headers.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,cAAc,EACd,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { admitPrincipal, authContext, requireAuth, requireNonGuest, requireRole, resolveSessionPrincipal } from './auth-context.js';
2
+ export { createRateLimiters, createRequestQuota, emailKeyOf, makeClientIp, principalBucketKey, quotaHeaderEntries, rateLimit } from './rate-limit.js';
3
+ export { requestId } from './request-id.js';
4
+ export { createScopeAllowlist, looksLikeJwt } from './scopes.js';
5
+ export { authBodyGuard } from './auth-body.js';
6
+ export { crossSiteGuard } from './cross-site.js';
7
+ export { idempotency, open, seal } from './idempotency.js';
8
+ export { MAX_JSON_DEPTH, exceedsJsonDepth, jsonDepthLimit } from './json-depth.js';
9
+ export { noStoreAuthenticated } from './no-store.js';
10
+ export { isPublicOauthPath, oauthPublicEndpoints } from './oauth-public.js';
11
+ export { buildCsp, hstsValue, inlineScriptHashes, securityHeaders } from './security-headers.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,WAAW,EACX,WAAW,EACX,eAAe,EACf,WAAW,EACX,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAML,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAA8C,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ /**
3
+ * Nesting cap for request JSON. Deliberately far above anything a contract in
4
+ * `@antasphere/contract` describes (the deepest is three or four levels) and far
5
+ * below the depth at which V8 recursion breaks.
6
+ *
7
+ * Why a cap at all: `JSON.parse` is iterative and swallows any depth, but
8
+ * `JSON.stringify` is RECURSIVE and blows the stack with a `RangeError` past a
9
+ * few thousand levels — and the exact depth depends on the V8 build, so it
10
+ * reproduces inside the shipped `node:22-alpine` image and not on a newer host
11
+ * Node. Every path that echoes, audits, logs, or persists a validated body
12
+ * stringifies it, so an anonymous client could turn one small request body
13
+ * into a 500 plus an error-level stack trace. Rejecting at the edge — before
14
+ * anything parses, let alone stringifies — is the only place the fix is
15
+ * complete.
16
+ */
17
+ export declare const MAX_JSON_DEPTH = 100;
18
+ /**
19
+ * True when `text` nests `{`/`[` deeper than `max`. A single string-aware
20
+ * scan, no parsing and no allocation: brackets inside JSON string literals
21
+ * (and escaped quotes inside them) do not count. Returns as soon as the limit
22
+ * is passed, so a hostile body costs O(prefix), not O(body).
23
+ */
24
+ export declare function exceedsJsonDepth(text: string, max: number): boolean;
25
+ /**
26
+ * Rejects over-deep JSON bodies with a 400 before any handler, parser or
27
+ * serializer sees them. Non-JSON and bodyless requests pass untouched, so
28
+ * streamed uploads and form-encoded token calls are unaffected. Mount it
29
+ * AFTER the body-size limit so the scan is bounded by that cap.
30
+ */
31
+ export declare function jsonDepthLimit(maxDepth?: number): MiddlewareHandler;
32
+ //# sourceMappingURL=json-depth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-depth.d.ts","sourceRoot":"","sources":["../../src/middleware/json-depth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAG9C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAKlC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAmBnE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAuB,GAAG,iBAAiB,CAiBnF"}