@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,463 @@
1
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
+ import type { StartedPostgreSqlContainer } from '@testcontainers/postgresql';
3
+ import { workspaceMembers } from '@antasphere/chassis-db';
4
+ import {
5
+ createDatabase,
6
+ createTestApp,
7
+ extractCookie,
8
+ readJson,
9
+ startPostgres,
10
+ type TestApp,
11
+ SETUP_TOKEN,
12
+ host
13
+ } from './helpers.js';
14
+
15
+ /**
16
+ * The eleven PROJECT tools the chassis registers beside `<toolPrefix>whoami`,
17
+ * and the two TEAM reads after them (PRDCT-2813, PRDCT-2794),
18
+ * driven as a real MCP client would: raw JSON-RPC POSTs against the stateless
19
+ * /mcp (Phase 7's harness), authenticated with the host's own API keys.
20
+ *
21
+ * A manager runs the whole life of a project through the tools alone —
22
+ * create, list, read, update, add a member by email, raise their role, remove
23
+ * them, archive, bring it back — and the two refusals that matter read as
24
+ * SENTENCES rather than as codes: a viewer told which role the act needs, a
25
+ * non-member told the project is not visible to them.
26
+ *
27
+ * Nothing here spells a tool's prefix or scope names: both come from `host`,
28
+ * because this file runs twice (this package's minimal host, and the tool's
29
+ * app over its real composition).
30
+ */
31
+ const PASSWORD = 'a-long-mcp-projects-password-1';
32
+ const OWNER = { email: 'owner@mcp-projects.test', name: 'Poppy Owner', password: PASSWORD };
33
+
34
+ const PREFIX = host.identity.mcp.toolPrefix;
35
+ const TOOL = {
36
+ list: `${PREFIX}list_projects`,
37
+ get: `${PREFIX}get_project`,
38
+ create: `${PREFIX}create_project`,
39
+ update: `${PREFIX}update_project`,
40
+ archive: `${PREFIX}archive_project`,
41
+ listMembers: `${PREFIX}list_project_members`,
42
+ addMember: `${PREFIX}add_project_member`,
43
+ setRole: `${PREFIX}set_project_member_role`,
44
+ removeMember: `${PREFIX}remove_project_member`,
45
+ setTeamRole: `${PREFIX}set_project_team_role`,
46
+ removeTeam: `${PREFIX}remove_project_team`,
47
+ listTeams: `${PREFIX}list_teams`,
48
+ listTeamMembers: `${PREFIX}list_team_members`
49
+ };
50
+
51
+ let container: StartedPostgreSqlContainer;
52
+ let app: TestApp;
53
+ let workspaceId = '';
54
+ let ownerCookie = '';
55
+ /** The manager's key drives the life of the project; the other two prove the refusals. */
56
+ let managerKey = '';
57
+ let viewerKey = '';
58
+ let outsiderKey = '';
59
+ let viewerUserId = '';
60
+ const viewerEmail = 'viewer@mcp-projects.test';
61
+
62
+ let ipCounter = 0;
63
+ const nextIp = () => `10.88.${Math.floor(ipCounter / 250)}.${(ipCounter++ % 250) + 1}`;
64
+
65
+ const json = (body: unknown, headers: Record<string, string> = {}) => ({
66
+ method: 'POST',
67
+ headers: { 'content-type': 'application/json', 'x-forwarded-for': nextIp(), ...headers },
68
+ body: JSON.stringify(body)
69
+ });
70
+
71
+ let rpcId = 0;
72
+
73
+ /** JSON-RPC result over the stateless /mcp (throws on protocol-level errors). */
74
+ async function rpc(key: string, method: string, params: unknown = {}) {
75
+ const res = await app.app.request('/mcp', {
76
+ method: 'POST',
77
+ headers: {
78
+ 'content-type': 'application/json',
79
+ accept: 'application/json, text/event-stream',
80
+ 'x-forwarded-for': nextIp(),
81
+ authorization: `Bearer ${key}`
82
+ },
83
+ body: JSON.stringify({ jsonrpc: '2.0', id: ++rpcId, method, params })
84
+ });
85
+ expect(res.status).toBe(200);
86
+ const body = await readJson(res);
87
+ expect(body.error, `JSON-RPC error for ${method}: ${JSON.stringify(body.error)}`).toBeUndefined();
88
+ return body.result;
89
+ }
90
+
91
+ /** Parse a tool's JSON text block; an error text is not JSON → null. */
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ function parseMaybe(text: string): any {
94
+ try {
95
+ return JSON.parse(text);
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+
101
+ /** Call one tool; `data` is the parsed JSON text block (an error text is not JSON). */
102
+ async function callTool(key: string, name: string, args: Record<string, unknown> = {}) {
103
+ const result = await rpc(key, 'tools/call', { name, arguments: args });
104
+ const text: string = result.content?.[0]?.text ?? '';
105
+ return { isError: result.isError === true, text, data: parseMaybe(text) };
106
+ }
107
+
108
+ /**
109
+ * A refusal must READ as a sentence, not stop at a code: `wrapToolErrors`
110
+ * appends ` — Next: <hint>` from the instance's hint table, and the chassis
111
+ * puts one there for every project code (`PROJECT_ERROR_HINTS`). The WORDS are
112
+ * the host's — a tool that words a code for its own domain overrides the
113
+ * chassis (`buildMcpServer`) — so what is pinned here is the shape: a hint
114
+ * exists, it is prose of some length, and it names `expected`.
115
+ */
116
+ function expectSentence(text: string, expected: RegExp): void {
117
+ const hint = text.split(' — Next: ')[1];
118
+ expect(hint, `no "Next:" sentence in: ${text}`).toBeTruthy();
119
+ expect(hint!.length, `the hint is not a sentence: ${hint}`).toBeGreaterThan(20);
120
+ expect(hint, `the hint does not name ${expected}: ${hint}`).toMatch(expected);
121
+ }
122
+
123
+ /** The tool call must have succeeded — the text is shown when it did not. */
124
+ async function ok(key: string, name: string, args: Record<string, unknown> = {}) {
125
+ const res = await callTool(key, name, args);
126
+ expect(res.isError, `${name}: ${res.text}`).toBe(false);
127
+ return res.data;
128
+ }
129
+
130
+ async function mintKey(cookie: string, name: string, scopes: string[]): Promise<string> {
131
+ const res = await app.app.request('/api/v1/api-keys', json({ name, scopes }, { cookie }));
132
+ expect(res.status).toBe(201);
133
+ return (await readJson(res)).key as string;
134
+ }
135
+
136
+ async function signIn(email: string): Promise<string> {
137
+ const res = await app.app.request('/api/v1/auth/sign-in/email', json({ email, password: PASSWORD }));
138
+ expect(res.status).toBe(200);
139
+ return extractCookie(res);
140
+ }
141
+
142
+ /** A plain workspace member with a read+write key of their own. */
143
+ async function addMember(name: string, email: string): Promise<{ userId: string; key: string }> {
144
+ const created = await app.auth.api.signUpEmail({ body: { email, password: PASSWORD, name } });
145
+ await app.db.db
146
+ .insert(workspaceMembers)
147
+ .values({ workspaceId, userId: created.user.id, role: 'member', origin: 'local' });
148
+ const key = await mintKey(await signIn(email), `${name}-rw`, [host.scopes.read, host.scopes.write]);
149
+ return { userId: created.user.id, key };
150
+ }
151
+
152
+ beforeAll(async () => {
153
+ container = await startPostgres();
154
+ app = await createTestApp(await createDatabase(container, 'mcp_projects'));
155
+
156
+ const setup = await app.app.request(
157
+ '/api/v1/setup',
158
+ json({ setupToken: SETUP_TOKEN, instanceName: 'MCP Projects', owner: OWNER })
159
+ );
160
+ expect(setup.status).toBe(201);
161
+ ownerCookie = await signIn(OWNER.email);
162
+ // The owner acts as a manager on every project: they are the "manager" here.
163
+ managerKey = await mintKey(ownerCookie, 'manager-rw', [host.scopes.read, host.scopes.write]);
164
+ workspaceId = (await readJson(await app.app.request('/api/v1/me', { headers: { cookie: ownerCookie } })))
165
+ .workspace.id;
166
+
167
+ const viewer = await addMember('Vera Viewer', viewerEmail);
168
+ viewerUserId = viewer.userId;
169
+ viewerKey = viewer.key;
170
+ outsiderKey = (await addMember('Otto Outsider', 'outsider@mcp-projects.test')).key;
171
+ }, 240_000);
172
+
173
+ afterAll(async () => {
174
+ await app?.stop();
175
+ await container?.stop();
176
+ });
177
+
178
+ describe('the project and team tools are served under the host prefix', () => {
179
+ it('tools/list carries all of them, with the read ones flagged read-only', async () => {
180
+ interface ToolInfo {
181
+ name: string;
182
+ description: string;
183
+ inputSchema?: { properties?: Record<string, unknown> };
184
+ annotations?: { readOnlyHint?: boolean; destructiveHint?: boolean };
185
+ }
186
+ const tools = (await rpc(managerKey, 'tools/list')).tools as ToolInfo[];
187
+ const byName = new Map(tools.map((t) => [t.name, t]));
188
+ for (const name of Object.values(TOOL)) {
189
+ expect(byName.has(name), `missing tool ${name}`).toBe(true);
190
+ // Org as a parameter: every tool of the set takes the workspace argument.
191
+ expect(byName.get(name)!.inputSchema?.properties?.workspace, `${name} lacks workspace`).toBeDefined();
192
+ }
193
+ for (const name of [TOOL.list, TOOL.get, TOOL.listMembers, TOOL.listTeams, TOOL.listTeamMembers]) {
194
+ expect(byName.get(name)!.annotations?.readOnlyHint, `${name} readOnlyHint`).toBe(true);
195
+ }
196
+ expect(byName.get(TOOL.removeMember)!.annotations?.destructiveHint, 'remove destructiveHint').toBe(true);
197
+ expect(byName.get(TOOL.removeTeam)!.annotations?.destructiveHint, 'remove team destructiveHint').toBe(
198
+ true
199
+ );
200
+ // The team tools are reads only: shaping a team is a person's act.
201
+ expect(byName.get(TOOL.listTeams)!.description).toContain('never through these tools');
202
+ expect(byName.get(TOOL.addMember)!.inputSchema?.properties?.teamId).toBeDefined();
203
+ // Archiving is a reversible switch (the same tool brings the project
204
+ // back), so it carries no destructive flag: a host that gates
205
+ // destructive tools must not block the restore.
206
+ expect(byName.get(TOOL.archive)!.annotations?.destructiveHint).toBeUndefined();
207
+ // The writes describe themselves confirm-first, and the set explains what a
208
+ // project IS to an agent that has never seen one.
209
+ for (const name of [
210
+ TOOL.create,
211
+ TOOL.update,
212
+ TOOL.archive,
213
+ TOOL.addMember,
214
+ TOOL.setRole,
215
+ TOOL.removeMember,
216
+ TOOL.setTeamRole,
217
+ TOOL.removeTeam
218
+ ]) {
219
+ expect(byName.get(name)!.description, `${name} confirm-first`).toContain('confirm with the user');
220
+ }
221
+ expect(byName.get(TOOL.list)!.description).toContain('subgroup of an organization');
222
+ expect(byName.get(TOOL.get)!.description).toContain('viewer');
223
+ expect(byName.get(TOOL.get)!.description).toContain('manager');
224
+ });
225
+ });
226
+
227
+ describe('a manager runs the life of a project through the tools', () => {
228
+ let projectId = '';
229
+
230
+ it('creates one, and the creator is its manager', async () => {
231
+ const created = await ok(managerKey, TOOL.create, {
232
+ name: 'Atlas',
233
+ description: 'The map work',
234
+ metadata: { tier: 'gold' }
235
+ });
236
+ expect(created.name).toBe('Atlas');
237
+ expect(created.description).toBe('The map work');
238
+ expect(created.metadata).toEqual({ tier: 'gold' });
239
+ expect(created.myRole).toBe('manager');
240
+ expect(created.archivedAt).toBeNull();
241
+ expect(created.memberCount).toBe(1);
242
+ projectId = created.id;
243
+ });
244
+
245
+ it('lists it, and reads it back with the caller’s own role', async () => {
246
+ const list = await ok(managerKey, TOOL.list);
247
+ expect(list.projects.map((p: { id: string }) => p.id)).toContain(projectId);
248
+ expect(list).toHaveProperty('nextCursor');
249
+
250
+ const one = await ok(managerKey, TOOL.get, { projectId });
251
+ expect(one.id).toBe(projectId);
252
+ expect(one.myRole).toBe('manager');
253
+ });
254
+
255
+ it('updates the name and replaces the metadata object', async () => {
256
+ const updated = await ok(managerKey, TOOL.update, {
257
+ projectId,
258
+ name: 'Atlas II',
259
+ metadata: { tier: 'platinum' }
260
+ });
261
+ expect(updated.name).toBe('Atlas II');
262
+ expect(updated.metadata).toEqual({ tier: 'platinum' });
263
+ // Untouched fields stay as they were.
264
+ expect(updated.description).toBe('The map work');
265
+ });
266
+
267
+ it('refuses an update that changes nothing, before any API call', async () => {
268
+ const res = await callTool(managerKey, TOOL.update, { projectId });
269
+ expect(res.isError).toBe(true);
270
+ expect(res.text).toContain('at least one of name, description or metadata');
271
+ });
272
+
273
+ it('adds a member by email, and the member list shows their role', async () => {
274
+ const added = await ok(managerKey, TOOL.addMember, {
275
+ projectId,
276
+ email: viewerEmail,
277
+ role: 'viewer'
278
+ });
279
+ expect(added.userId).toBe(viewerUserId);
280
+ expect(added.role).toBe('viewer');
281
+
282
+ const members = await ok(managerKey, TOOL.listMembers, { projectId });
283
+ const roles = new Map(members.members.map((m: { userId: string; role: string }) => [m.userId, m.role]));
284
+ expect(roles.get(viewerUserId)).toBe('viewer');
285
+ expect(members).toHaveProperty('nextCursor');
286
+ });
287
+
288
+ it('refuses a member named both ways, or neither, before any API call', async () => {
289
+ for (const args of [
290
+ { projectId, role: 'viewer' },
291
+ { projectId, role: 'viewer', userId: viewerUserId, email: viewerEmail },
292
+ { projectId, role: 'viewer', email: viewerEmail, teamId: '00000000-0000-4000-8000-000000000000' }
293
+ ]) {
294
+ const res = await callTool(managerKey, TOOL.addMember, args);
295
+ expect(res.isError).toBe(true);
296
+ expect(res.text).toContain('Name exactly one member');
297
+ }
298
+ });
299
+
300
+ it('raises the member to editor, then removes them from the project', async () => {
301
+ const raised = await ok(managerKey, TOOL.setRole, {
302
+ projectId,
303
+ userId: viewerUserId,
304
+ role: 'editor'
305
+ });
306
+ expect(raised.role).toBe('editor');
307
+
308
+ const removed = await ok(managerKey, TOOL.removeMember, { projectId, userId: viewerUserId });
309
+ expect(removed.userId).toBe(viewerUserId);
310
+ const after = await ok(managerKey, TOOL.listMembers, { projectId });
311
+ expect(after.members.map((m: { userId: string }) => m.userId)).not.toContain(viewerUserId);
312
+ });
313
+
314
+ it('archives it: out of the default list, and read-only in plain words', async () => {
315
+ const archived = await ok(managerKey, TOOL.archive, { projectId });
316
+ expect(archived.archivedAt).not.toBeNull();
317
+
318
+ const live = await ok(managerKey, TOOL.list);
319
+ expect(live.projects.map((p: { id: string }) => p.id)).not.toContain(projectId);
320
+ const all = await ok(managerKey, TOOL.list, { archived: 'true' });
321
+ expect(all.projects.map((p: { id: string }) => p.id)).toContain(projectId);
322
+
323
+ const refused = await callTool(managerKey, TOOL.update, { projectId, name: 'Atlas III' });
324
+ expect(refused.isError).toBe(true);
325
+ expect(refused.text).toContain('project_archived');
326
+ // The code is followed by a SENTENCE, not left as a code: a hint saying
327
+ // what to do about it. The chassis words every project code
328
+ // (`PROJECT_ERROR_HINTS`), and a host that words one for its own domain
329
+ // wins — so the words are the host's and only the shape is pinned here.
330
+ expectSentence(refused.text, /unarchiv|archived/i);
331
+ });
332
+
333
+ it('brings it back with the same tool, and it is writable again', async () => {
334
+ const back = await ok(managerKey, TOOL.archive, { projectId, archived: false });
335
+ expect(back.archivedAt).toBeNull();
336
+ const renamed = await ok(managerKey, TOOL.update, { projectId, name: 'Atlas III' });
337
+ expect(renamed.name).toBe('Atlas III');
338
+ });
339
+ });
340
+
341
+ describe('the refusals read as sentences', () => {
342
+ let projectId = '';
343
+
344
+ beforeAll(async () => {
345
+ projectId = (await ok(managerKey, TOOL.create, { name: 'Bastion' })).id;
346
+ await ok(managerKey, TOOL.addMember, { projectId, email: viewerEmail, role: 'viewer' });
347
+ });
348
+
349
+ it('a viewer reads the project but is told which role the change needs', async () => {
350
+ const read = await ok(viewerKey, TOOL.get, { projectId });
351
+ expect(read.myRole).toBe('viewer');
352
+
353
+ const refused = await callTool(viewerKey, TOOL.update, { projectId, name: 'Bastion II' });
354
+ expect(refused.isError).toBe(true);
355
+ expect(refused.text).toContain('insufficient_project_role');
356
+ // Words, not a bare code — and the role the act needs is named.
357
+ expectSentence(refused.text, /manager/i);
358
+ });
359
+
360
+ it('a viewer may not manage the members either', async () => {
361
+ const refused = await callTool(viewerKey, TOOL.addMember, {
362
+ projectId,
363
+ email: OWNER.email,
364
+ role: 'editor'
365
+ });
366
+ expect(refused.isError).toBe(true);
367
+ expect(refused.text).toContain('insufficient_project_role');
368
+ expectSentence(refused.text, /manager/i);
369
+ });
370
+
371
+ it('a non-member is told not found, never that the project exists', async () => {
372
+ const refused = await callTool(outsiderKey, TOOL.get, { projectId });
373
+ expect(refused.isError).toBe(true);
374
+ expect(refused.text).toContain('HTTP 404');
375
+ expect(refused.text).toContain('not_found');
376
+ // Never the shape of a permission refusal: existence is not probeable. The
377
+ // 404's own WORDS are the host's (`not_found` is the whole instance's code,
378
+ // which a tool words for its domain), so only the tier is pinned here.
379
+ expect(refused.text).not.toContain('403');
380
+ expect(refused.text).not.toContain('insufficient_project_role');
381
+
382
+ const mine = await ok(outsiderKey, TOOL.list);
383
+ expect(mine.projects.map((p: { id: string }) => p.id)).not.toContain(projectId);
384
+ });
385
+
386
+ it('a key without the write scope is told so before the API is reached', async () => {
387
+ const readOnly = await mintKey(await signIn(OWNER.email), 'manager-ro', [host.scopes.read]);
388
+ const refused = await callTool(readOnly, TOOL.create, { name: 'Never' });
389
+ expect(refused.isError).toBe(true);
390
+ expect(refused.text).toContain(`Missing scope "${host.scopes.write}"`);
391
+ // The read half of the set still works on the same key.
392
+ expect((await ok(readOnly, TOOL.list)).projects).toBeInstanceOf(Array);
393
+ });
394
+ });
395
+
396
+ describe('a team, read through the tools and put on a project', () => {
397
+ let teamId = '';
398
+ let projectId = '';
399
+
400
+ beforeAll(async () => {
401
+ // The team is shaped over the app, as a person does on the People page:
402
+ // the tools only read teams.
403
+ const created = await app.app.request(
404
+ '/api/v1/teams',
405
+ json({ name: 'Cartographers' }, { cookie: ownerCookie })
406
+ );
407
+ expect(created.status).toBe(201);
408
+ teamId = (await readJson(created)).id as string;
409
+ const seated = await app.app.request(
410
+ `/api/v1/teams/${teamId}/members`,
411
+ json({ email: viewerEmail }, { cookie: ownerCookie })
412
+ );
413
+ expect(seated.status).toBe(201);
414
+ projectId = (await ok(managerKey, TOOL.create, { name: 'Compass' })).id;
415
+ });
416
+
417
+ it('list_teams shows the team, list_team_members its member', async () => {
418
+ const teams = await ok(managerKey, TOOL.listTeams);
419
+ const team = teams.teams.find((t: { id: string }) => t.id === teamId);
420
+ expect(team).toMatchObject({
421
+ slug: 'cartographers',
422
+ name: 'Cartographers',
423
+ membersCount: 1,
424
+ hubTeamId: null
425
+ });
426
+ expect(teams).toHaveProperty('nextCursor');
427
+
428
+ const members = await ok(viewerKey, TOOL.listTeamMembers, { teamId });
429
+ expect(members.members.map((m: { userId: string }) => m.userId)).toEqual([viewerUserId]);
430
+ });
431
+
432
+ it('add_project_member with teamId puts the team on the project, and its member reads it', async () => {
433
+ const before = await callTool(viewerKey, TOOL.get, { projectId });
434
+ expect(before.isError).toBe(true);
435
+
436
+ const added = await ok(managerKey, TOOL.addMember, { projectId, teamId, role: 'viewer' });
437
+ expect(added).toMatchObject({ kind: 'team', teamId, slug: 'cartographers', role: 'viewer' });
438
+
439
+ const members = await ok(managerKey, TOOL.listMembers, { projectId });
440
+ const entry = members.members.find((m: { kind: string; teamId?: string }) => m.teamId === teamId);
441
+ expect(entry?.kind).toBe('team');
442
+
443
+ const read = await ok(viewerKey, TOOL.get, { projectId });
444
+ expect(read.myRole).toBe('viewer');
445
+ });
446
+
447
+ it('set_project_team_role raises the team, remove_project_team takes it off', async () => {
448
+ const raised = await ok(managerKey, TOOL.setTeamRole, { projectId, teamId, role: 'editor' });
449
+ expect(raised.role).toBe('editor');
450
+ expect((await ok(viewerKey, TOOL.get, { projectId })).myRole).toBe('editor');
451
+
452
+ const removed = await ok(managerKey, TOOL.removeTeam, { projectId, teamId });
453
+ expect(removed.teamId).toBe(teamId);
454
+ const after = await callTool(viewerKey, TOOL.get, { projectId });
455
+ expect(after.isError).toBe(true);
456
+ expect(after.text).toContain('not_found');
457
+
458
+ const again = await callTool(managerKey, TOOL.removeTeam, { projectId, teamId });
459
+ expect(again.isError).toBe(true);
460
+ expect(again.text).toContain('team_not_found');
461
+ expectSentence(again.text, /team/i);
462
+ });
463
+ });