cursedbelt-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 (606) hide show
  1. package/LICENSE +15 -0
  2. package/dist/server/activity/index.d.ts +36 -0
  3. package/dist/server/activity/index.js +36 -0
  4. package/dist/server/activity/migrations.d.ts +21 -0
  5. package/dist/server/activity/migrations.js +55 -0
  6. package/dist/server/activity/shareSource.d.ts +11 -0
  7. package/dist/server/activity/shareSource.js +45 -0
  8. package/dist/server/activity/store.d.ts +123 -0
  9. package/dist/server/activity/store.js +178 -0
  10. package/dist/server/app.d.ts +56 -0
  11. package/dist/server/app.js +45 -0
  12. package/dist/server/audit/index.d.ts +2 -0
  13. package/dist/server/audit/index.js +2 -0
  14. package/dist/server/audit/migrations.d.ts +2 -0
  15. package/dist/server/audit/migrations.js +79 -0
  16. package/dist/server/audit/sqliteSink.d.ts +36 -0
  17. package/dist/server/audit/sqliteSink.js +95 -0
  18. package/dist/server/audit/sqliteSink.test.d.ts +1 -0
  19. package/dist/server/audit/sqliteSink.test.js +180 -0
  20. package/dist/server/auth/cookie.d.ts +22 -0
  21. package/dist/server/auth/cookie.js +35 -0
  22. package/dist/server/auth/csrf.d.ts +42 -0
  23. package/dist/server/auth/csrf.js +36 -0
  24. package/dist/server/auth/fileTokenSigner.d.ts +10 -0
  25. package/dist/server/auth/fileTokenSigner.js +22 -0
  26. package/dist/server/auth/getOnly.d.ts +20 -0
  27. package/dist/server/auth/getOnly.js +27 -0
  28. package/dist/server/auth/index.d.ts +12 -0
  29. package/dist/server/auth/index.js +15 -0
  30. package/dist/server/auth/jwt.d.ts +18 -0
  31. package/dist/server/auth/jwt.js +56 -0
  32. package/dist/server/auth/loginThrottle.d.ts +118 -0
  33. package/dist/server/auth/loginThrottle.js +204 -0
  34. package/dist/server/auth/middleware.d.ts +14 -0
  35. package/dist/server/auth/middleware.js +47 -0
  36. package/dist/server/auth/password.d.ts +14 -0
  37. package/dist/server/auth/password.js +65 -0
  38. package/dist/server/auth/sessionStore.d.ts +19 -0
  39. package/dist/server/auth/sessionStore.js +221 -0
  40. package/dist/server/auth/totp.d.ts +34 -0
  41. package/dist/server/auth/totp.js +81 -0
  42. package/dist/server/auth/types.d.ts +133 -0
  43. package/dist/server/auth/types.js +1 -0
  44. package/dist/server/auth/vault.d.ts +27 -0
  45. package/dist/server/auth/vault.js +57 -0
  46. package/dist/server/context.d.ts +35 -0
  47. package/dist/server/context.js +1 -0
  48. package/dist/server/ctgr.d.ts +32 -0
  49. package/dist/server/ctgr.js +69 -0
  50. package/dist/server/db/kysely.d.ts +14 -0
  51. package/dist/server/db/kysely.js +16 -0
  52. package/dist/server/db/plumbingTypes.d.ts +116 -0
  53. package/dist/server/db/plumbingTypes.js +12 -0
  54. package/dist/server/dropzone/duplicates.d.ts +82 -0
  55. package/dist/server/dropzone/duplicates.js +90 -0
  56. package/dist/server/dropzone/index.d.ts +13 -0
  57. package/dist/server/dropzone/index.js +13 -0
  58. package/dist/server/dropzone/scan.d.ts +166 -0
  59. package/dist/server/dropzone/scan.js +272 -0
  60. package/dist/server/errors.d.ts +7 -0
  61. package/dist/server/errors.js +7 -0
  62. package/dist/server/guard/argon2Binding.d.ts +97 -0
  63. package/dist/server/guard/argon2Binding.js +138 -0
  64. package/dist/server/guard/index.d.ts +4 -0
  65. package/dist/server/guard/index.js +6 -0
  66. package/dist/server/guard/kdfWorker.d.ts +101 -0
  67. package/dist/server/guard/kdfWorker.js +301 -0
  68. package/dist/server/guard/kdfWorkerEntry.d.ts +1 -0
  69. package/dist/server/guard/kdfWorkerEntry.js +15 -0
  70. package/dist/server/guard/passwordVerifier.d.ts +65 -0
  71. package/dist/server/guard/passwordVerifier.js +122 -0
  72. package/dist/server/guard/revocationStore.d.ts +132 -0
  73. package/dist/server/guard/revocationStore.js +211 -0
  74. package/dist/server/guard/sessionSigner.d.ts +132 -0
  75. package/dist/server/guard/sessionSigner.js +303 -0
  76. package/dist/server/guard/verifier.d.ts +21 -0
  77. package/dist/server/guard/verifier.js +1 -0
  78. package/dist/server/incidents/channels.d.ts +161 -0
  79. package/dist/server/incidents/channels.js +357 -0
  80. package/dist/server/incidents/checks.d.ts +61 -0
  81. package/dist/server/incidents/checks.js +55 -0
  82. package/dist/server/incidents/index.d.ts +51 -0
  83. package/dist/server/incidents/index.js +51 -0
  84. package/dist/server/incidents/migrations.d.ts +20 -0
  85. package/dist/server/incidents/migrations.js +58 -0
  86. package/dist/server/incidents/notifier.d.ts +79 -0
  87. package/dist/server/incidents/notifier.js +141 -0
  88. package/dist/server/incidents/reporter.d.ts +60 -0
  89. package/dist/server/incidents/reporter.js +49 -0
  90. package/dist/server/incidents/routes.d.ts +91 -0
  91. package/dist/server/incidents/routes.js +202 -0
  92. package/dist/server/incidents/store.d.ts +75 -0
  93. package/dist/server/incidents/store.js +176 -0
  94. package/dist/server/incidents/types.d.ts +107 -0
  95. package/dist/server/incidents/types.js +32 -0
  96. package/dist/server/index.d.ts +25 -0
  97. package/dist/server/index.js +53 -0
  98. package/dist/server/jobs/fireQueue.d.ts +12 -0
  99. package/dist/server/jobs/fireQueue.js +37 -0
  100. package/dist/server/jobs/index.d.ts +6 -0
  101. package/dist/server/jobs/index.js +10 -0
  102. package/dist/server/jobs/logger.d.ts +10 -0
  103. package/dist/server/jobs/logger.js +14 -0
  104. package/dist/server/jobs/plainjobAdapter.d.ts +19 -0
  105. package/dist/server/jobs/plainjobAdapter.js +48 -0
  106. package/dist/server/jobs/polling.d.ts +17 -0
  107. package/dist/server/jobs/polling.js +79 -0
  108. package/dist/server/jobs/runner.d.ts +24 -0
  109. package/dist/server/jobs/runner.js +186 -0
  110. package/dist/server/jobs/timeout.d.ts +28 -0
  111. package/dist/server/jobs/timeout.js +47 -0
  112. package/dist/server/jobs/types.d.ts +167 -0
  113. package/dist/server/jobs/types.js +12 -0
  114. package/dist/server/master-lock/guard.d.ts +53 -0
  115. package/dist/server/master-lock/guard.js +205 -0
  116. package/dist/server/master-lock/index.d.ts +21 -0
  117. package/dist/server/master-lock/index.js +21 -0
  118. package/dist/server/master-lock/lockPage.d.ts +34 -0
  119. package/dist/server/master-lock/lockPage.js +281 -0
  120. package/dist/server/master-lock/masterLock.d.ts +294 -0
  121. package/dist/server/master-lock/masterLock.js +523 -0
  122. package/dist/server/master-lock/principals.d.ts +76 -0
  123. package/dist/server/master-lock/principals.js +157 -0
  124. package/dist/server/master-lock/seed.d.ts +47 -0
  125. package/dist/server/master-lock/seed.js +93 -0
  126. package/dist/server/master-lock/store.d.ts +19 -0
  127. package/dist/server/master-lock/store.js +20 -0
  128. package/dist/server/media-bun/image.d.ts +7 -0
  129. package/dist/server/media-bun/image.js +96 -0
  130. package/dist/server/media-bun/index.d.ts +4 -0
  131. package/dist/server/media-bun/index.js +10 -0
  132. package/dist/server/media-bun/streaming.d.ts +86 -0
  133. package/dist/server/media-bun/streaming.js +237 -0
  134. package/dist/server/media-bun/video.d.ts +35 -0
  135. package/dist/server/media-bun/video.js +181 -0
  136. package/dist/server/metrics/metricsBuffer.d.ts +39 -0
  137. package/dist/server/metrics/metricsBuffer.js +36 -0
  138. package/dist/server/metrics/normalizeRoute.d.ts +5 -0
  139. package/dist/server/metrics/normalizeRoute.js +58 -0
  140. package/dist/server/middleware/correlationId.d.ts +9 -0
  141. package/dist/server/middleware/correlationId.js +20 -0
  142. package/dist/server/middleware/corsAllowlist.d.ts +38 -0
  143. package/dist/server/middleware/corsAllowlist.js +37 -0
  144. package/dist/server/middleware/errorEnvelope.d.ts +17 -0
  145. package/dist/server/middleware/errorEnvelope.js +32 -0
  146. package/dist/server/middleware/index.d.ts +9 -0
  147. package/dist/server/middleware/index.js +10 -0
  148. package/dist/server/middleware/localOrigin.d.ts +71 -0
  149. package/dist/server/middleware/localOrigin.js +119 -0
  150. package/dist/server/middleware/rateLimit.d.ts +56 -0
  151. package/dist/server/middleware/rateLimit.js +86 -0
  152. package/dist/server/middleware/requestLogger.d.ts +29 -0
  153. package/dist/server/middleware/requestLogger.js +47 -0
  154. package/dist/server/middleware/securityHeaders.d.ts +29 -0
  155. package/dist/server/middleware/securityHeaders.js +44 -0
  156. package/dist/server/middleware/zValidator.d.ts +29 -0
  157. package/dist/server/middleware/zValidator.js +57 -0
  158. package/dist/server/migration/runner.d.ts +42 -0
  159. package/dist/server/migration/runner.js +70 -0
  160. package/dist/server/migration/types.d.ts +16 -0
  161. package/dist/server/migration/types.js +1 -0
  162. package/dist/server/net/outboundGuard.d.ts +30 -0
  163. package/dist/server/net/outboundGuard.js +199 -0
  164. package/dist/server/notifications/hub.d.ts +67 -0
  165. package/dist/server/notifications/hub.js +187 -0
  166. package/dist/server/notifications/index.d.ts +47 -0
  167. package/dist/server/notifications/index.js +46 -0
  168. package/dist/server/notifications/migrations.d.ts +13 -0
  169. package/dist/server/notifications/migrations.js +20 -0
  170. package/dist/server/notifications/routes.d.ts +58 -0
  171. package/dist/server/notifications/routes.js +113 -0
  172. package/dist/server/notifications/service.d.ts +58 -0
  173. package/dist/server/notifications/service.js +41 -0
  174. package/dist/server/paths/appDataHome.d.ts +19 -0
  175. package/dist/server/paths/appDataHome.js +68 -0
  176. package/dist/server/private-media/crypto.d.ts +37 -0
  177. package/dist/server/private-media/crypto.js +111 -0
  178. package/dist/server/private-media/index-store.d.ts +31 -0
  179. package/dist/server/private-media/index-store.js +36 -0
  180. package/dist/server/private-media/mountPrivateRoutes.d.ts +26 -0
  181. package/dist/server/private-media/mountPrivateRoutes.js +219 -0
  182. package/dist/server/private-media/pipeline.d.ts +37 -0
  183. package/dist/server/private-media/pipeline.js +97 -0
  184. package/dist/server/private-media/unlock.d.ts +52 -0
  185. package/dist/server/private-media/unlock.js +55 -0
  186. package/dist/server/resume/index.d.ts +2 -0
  187. package/dist/server/resume/index.js +2 -0
  188. package/dist/server/resume/routes.d.ts +41 -0
  189. package/dist/server/resume/routes.js +50 -0
  190. package/dist/server/resume/store.d.ts +37 -0
  191. package/dist/server/resume/store.js +38 -0
  192. package/dist/server/retention/archive.d.ts +78 -0
  193. package/dist/server/retention/archive.js +284 -0
  194. package/dist/server/retention/fleet.d.ts +50 -0
  195. package/dist/server/retention/fleet.js +66 -0
  196. package/dist/server/retention/index.d.ts +38 -0
  197. package/dist/server/retention/index.js +38 -0
  198. package/dist/server/retention/policy.d.ts +263 -0
  199. package/dist/server/retention/policy.js +264 -0
  200. package/dist/server/retention/store.d.ts +101 -0
  201. package/dist/server/retention/store.js +251 -0
  202. package/dist/server/retention/sweeper.d.ts +69 -0
  203. package/dist/server/retention/sweeper.js +289 -0
  204. package/dist/server/retention/target.d.ts +143 -0
  205. package/dist/server/retention/target.js +438 -0
  206. package/dist/server/search/index.d.ts +2 -0
  207. package/dist/server/search/index.js +6 -0
  208. package/dist/server/search/pgSearchProvider.d.ts +91 -0
  209. package/dist/server/search/pgSearchProvider.js +330 -0
  210. package/dist/server/search/pgSearchProvider.pg.test.d.ts +1 -0
  211. package/dist/server/search/pgSearchProvider.pg.test.js +338 -0
  212. package/dist/server/search/pgSearchSchema.d.ts +81 -0
  213. package/dist/server/search/pgSearchSchema.js +89 -0
  214. package/dist/server/sharing/index.d.ts +18 -0
  215. package/dist/server/sharing/index.js +16 -0
  216. package/dist/server/sharing/migrations.d.ts +6 -0
  217. package/dist/server/sharing/migrations.js +79 -0
  218. package/dist/server/sharing/router.d.ts +111 -0
  219. package/dist/server/sharing/router.js +93 -0
  220. package/dist/server/sharing/sql.d.ts +67 -0
  221. package/dist/server/sharing/sql.js +88 -0
  222. package/dist/server/sharing/store.d.ts +173 -0
  223. package/dist/server/sharing/store.js +484 -0
  224. package/dist/server/sqlite/backup.d.ts +48 -0
  225. package/dist/server/sqlite/backup.js +97 -0
  226. package/dist/server/sqlite/browse.d.ts +42 -0
  227. package/dist/server/sqlite/browse.js +84 -0
  228. package/dist/server/sqlite/export.d.ts +32 -0
  229. package/dist/server/sqlite/export.js +42 -0
  230. package/dist/server/sqlite/fts5.d.ts +106 -0
  231. package/dist/server/sqlite/fts5.js +154 -0
  232. package/dist/server/sqlite/health.d.ts +44 -0
  233. package/dist/server/sqlite/health.js +52 -0
  234. package/dist/server/sqlite/import.d.ts +36 -0
  235. package/dist/server/sqlite/import.js +108 -0
  236. package/dist/server/sqlite/index.d.ts +9 -0
  237. package/dist/server/sqlite/index.js +15 -0
  238. package/dist/server/sqlite/readonlySql.d.ts +15 -0
  239. package/dist/server/sqlite/readonlySql.js +65 -0
  240. package/dist/server/sqlite/stats.d.ts +22 -0
  241. package/dist/server/sqlite/stats.js +32 -0
  242. package/dist/server/sqlite/viewer.d.ts +17 -0
  243. package/dist/server/sqlite/viewer.js +56 -0
  244. package/dist/server/storage/binaryServerProcessing.d.ts +23 -0
  245. package/dist/server/storage/binaryServerProcessing.js +81 -0
  246. package/dist/server/storage/binaryServerStore.d.ts +3 -0
  247. package/dist/server/storage/binaryServerStore.js +95 -0
  248. package/dist/server/storage/diskStore.d.ts +2 -0
  249. package/dist/server/storage/diskStore.js +88 -0
  250. package/dist/server/storage/files/adapter.d.ts +33 -0
  251. package/dist/server/storage/files/adapter.js +203 -0
  252. package/dist/server/storage/files/catalogue.d.ts +72 -0
  253. package/dist/server/storage/files/catalogue.js +1033 -0
  254. package/dist/server/storage/files/chunkedUpload.d.ts +56 -0
  255. package/dist/server/storage/files/chunkedUpload.js +70 -0
  256. package/dist/server/storage/files/fileRoutes.d.ts +51 -0
  257. package/dist/server/storage/files/fileRoutes.js +405 -0
  258. package/dist/server/storage/files/index.d.ts +9 -0
  259. package/dist/server/storage/files/index.js +11 -0
  260. package/dist/server/storage/files/migrations.d.ts +2 -0
  261. package/dist/server/storage/files/migrations.js +163 -0
  262. package/dist/server/storage/files/mimeByExt.d.ts +1 -0
  263. package/dist/server/storage/files/mimeByExt.js +13 -0
  264. package/dist/server/storage/files/stack.d.ts +136 -0
  265. package/dist/server/storage/files/stack.js +132 -0
  266. package/dist/server/storage/files/storageOps.d.ts +54 -0
  267. package/dist/server/storage/files/storageOps.js +110 -0
  268. package/dist/server/storage/files/types.d.ts +261 -0
  269. package/dist/server/storage/files/types.js +22 -0
  270. package/dist/server/storage/imageThumbnail.d.ts +3 -0
  271. package/dist/server/storage/imageThumbnail.js +50 -0
  272. package/dist/server/storage/index.d.ts +15 -0
  273. package/dist/server/storage/index.js +27 -0
  274. package/dist/server/storage/mountMediaRoutes.d.ts +28 -0
  275. package/dist/server/storage/mountMediaRoutes.js +141 -0
  276. package/dist/server/storage/objectStoreMediaStore.d.ts +4 -0
  277. package/dist/server/storage/objectStoreMediaStore.js +57 -0
  278. package/dist/server/storage/s3ObjectStore.d.ts +63 -0
  279. package/dist/server/storage/s3ObjectStore.js +187 -0
  280. package/dist/server/storage/sources.d.ts +47 -0
  281. package/dist/server/storage/sources.js +148 -0
  282. package/dist/server/storage/streamRange.d.ts +19 -0
  283. package/dist/server/storage/streamRange.js +69 -0
  284. package/dist/server/storage/streamToken.d.ts +16 -0
  285. package/dist/server/storage/streamToken.js +54 -0
  286. package/dist/server/storage/transcodeJobs.d.ts +65 -0
  287. package/dist/server/storage/transcodeJobs.js +104 -0
  288. package/dist/server/storage/types.d.ts +193 -0
  289. package/dist/server/storage/types.js +41 -0
  290. package/dist/server/storage/videoDerivativeKeys.d.ts +127 -0
  291. package/dist/server/storage/videoDerivativeKeys.js +149 -0
  292. package/dist/server/storage/videoProcessor.d.ts +30 -0
  293. package/dist/server/storage/videoProcessor.js +148 -0
  294. package/dist/server/sync/alarm.d.ts +34 -0
  295. package/dist/server/sync/alarm.js +91 -0
  296. package/dist/server/sync/commands.d.ts +87 -0
  297. package/dist/server/sync/commands.js +241 -0
  298. package/dist/server/sync/engine.d.ts +62 -0
  299. package/dist/server/sync/engine.js +184 -0
  300. package/dist/server/sync/http.d.ts +106 -0
  301. package/dist/server/sync/http.js +243 -0
  302. package/dist/server/sync/index.d.ts +41 -0
  303. package/dist/server/sync/index.js +41 -0
  304. package/dist/server/sync/opLog.d.ts +61 -0
  305. package/dist/server/sync/opLog.js +96 -0
  306. package/dist/server/sync/planner.d.ts +31 -0
  307. package/dist/server/sync/planner.js +30 -0
  308. package/dist/server/sync/status.d.ts +63 -0
  309. package/dist/server/sync/status.js +49 -0
  310. package/dist/server/sync/timer.d.ts +52 -0
  311. package/dist/server/sync/timer.js +170 -0
  312. package/dist/server/sync/tokens.d.ts +25 -0
  313. package/dist/server/sync/tokens.js +51 -0
  314. package/dist/server/sync/types.d.ts +101 -0
  315. package/dist/server/sync/types.js +29 -0
  316. package/dist/server/ws/eventBus.d.ts +14 -0
  317. package/dist/server/ws/eventBus.js +42 -0
  318. package/dist/server/ws/hub.d.ts +20 -0
  319. package/dist/server/ws/hub.js +154 -0
  320. package/dist/server/ws/index.d.ts +5 -0
  321. package/dist/server/ws/index.js +7 -0
  322. package/dist/server/ws/presence.d.ts +11 -0
  323. package/dist/server/ws/presence.js +20 -0
  324. package/dist/server/ws/room.d.ts +17 -0
  325. package/dist/server/ws/room.js +23 -0
  326. package/dist/server/ws/types.d.ts +122 -0
  327. package/dist/server/ws/types.js +1 -0
  328. package/package.json +234 -0
  329. package/src/declaredDepsAreImported.spec.ts +87 -0
  330. package/src/leafSubpathsImportNothing.spec.ts +358 -0
  331. package/src/lockfileIsTracked.spec.ts +50 -0
  332. package/src/namedSubpathsResolve.spec.ts +122 -0
  333. package/src/noPathDeps.spec.ts +24 -0
  334. package/src/publishShape.spec.ts +89 -0
  335. package/src/server/activity/index.ts +59 -0
  336. package/src/server/activity/migrations.ts +67 -0
  337. package/src/server/activity/shareSource.ts +57 -0
  338. package/src/server/activity/store.spec.ts +255 -0
  339. package/src/server/activity/store.ts +368 -0
  340. package/src/server/app.spec.ts +243 -0
  341. package/src/server/app.ts +89 -0
  342. package/src/server/audit/index.ts +2 -0
  343. package/src/server/audit/migrations.ts +88 -0
  344. package/src/server/audit/sqliteSink.test.ts +200 -0
  345. package/src/server/audit/sqliteSink.ts +162 -0
  346. package/src/server/auth/cookie.spec.ts +46 -0
  347. package/src/server/auth/cookie.ts +42 -0
  348. package/src/server/auth/csrf.spec.ts +81 -0
  349. package/src/server/auth/csrf.ts +83 -0
  350. package/src/server/auth/fileTokenSigner.ts +40 -0
  351. package/src/server/auth/getOnly.spec.ts +53 -0
  352. package/src/server/auth/getOnly.ts +32 -0
  353. package/src/server/auth/index.ts +51 -0
  354. package/src/server/auth/jwt.spec.ts +106 -0
  355. package/src/server/auth/jwt.ts +75 -0
  356. package/src/server/auth/loginThrottle.spec.ts +213 -0
  357. package/src/server/auth/loginThrottle.ts +261 -0
  358. package/src/server/auth/middleware.spec.ts +148 -0
  359. package/src/server/auth/middleware.ts +56 -0
  360. package/src/server/auth/password.spec.ts +48 -0
  361. package/src/server/auth/password.ts +71 -0
  362. package/src/server/auth/sessionStore.spec.ts +189 -0
  363. package/src/server/auth/sessionStore.ts +261 -0
  364. package/src/server/auth/totp.spec.ts +73 -0
  365. package/src/server/auth/totp.ts +92 -0
  366. package/src/server/auth/types.ts +146 -0
  367. package/src/server/auth/vault.spec.ts +51 -0
  368. package/src/server/auth/vault.ts +71 -0
  369. package/src/server/context.ts +37 -0
  370. package/src/server/ctgr.spec.ts +138 -0
  371. package/src/server/ctgr.ts +108 -0
  372. package/src/server/db/kysely.spec.ts +62 -0
  373. package/src/server/db/kysely.ts +21 -0
  374. package/src/server/db/plumbingTypes.ts +126 -0
  375. package/src/server/dropzone/duplicates.ts +121 -0
  376. package/src/server/dropzone/index.ts +30 -0
  377. package/src/server/dropzone/scan.spec.ts +255 -0
  378. package/src/server/dropzone/scan.ts +342 -0
  379. package/src/server/errors.spec.ts +76 -0
  380. package/src/server/errors.ts +22 -0
  381. package/src/server/guard/argon2Binding.spec.ts +117 -0
  382. package/src/server/guard/argon2Binding.ts +195 -0
  383. package/src/server/guard/argon2Kat.spec.ts +250 -0
  384. package/src/server/guard/guard.spec.ts +390 -0
  385. package/src/server/guard/index.ts +6 -0
  386. package/src/server/guard/kdfWorker.spec.ts +283 -0
  387. package/src/server/guard/kdfWorker.ts +367 -0
  388. package/src/server/guard/kdfWorkerEntry.ts +16 -0
  389. package/src/server/guard/passwordVerifier.spec.ts +71 -0
  390. package/src/server/guard/passwordVerifier.ts +175 -0
  391. package/src/server/guard/revocationStore.spec.ts +135 -0
  392. package/src/server/guard/revocationStore.ts +291 -0
  393. package/src/server/guard/sessionSigner.ts +425 -0
  394. package/src/server/guard/verifier.ts +27 -0
  395. package/src/server/incidents/channels.ts +487 -0
  396. package/src/server/incidents/checks.ts +120 -0
  397. package/src/server/incidents/incidents.spec.ts +463 -0
  398. package/src/server/incidents/index.ts +96 -0
  399. package/src/server/incidents/migrations.ts +66 -0
  400. package/src/server/incidents/notifier.ts +215 -0
  401. package/src/server/incidents/reporter.ts +110 -0
  402. package/src/server/incidents/routes.ts +314 -0
  403. package/src/server/incidents/store.ts +329 -0
  404. package/src/server/incidents/types.ts +116 -0
  405. package/src/server/index.ts +248 -0
  406. package/src/server/jobs/fireQueue.spec.ts +85 -0
  407. package/src/server/jobs/fireQueue.ts +37 -0
  408. package/src/server/jobs/index.ts +26 -0
  409. package/src/server/jobs/logger.ts +16 -0
  410. package/src/server/jobs/plainjobAdapter.spec.ts +34 -0
  411. package/src/server/jobs/plainjobAdapter.ts +54 -0
  412. package/src/server/jobs/polling.spec.ts +219 -0
  413. package/src/server/jobs/polling.ts +81 -0
  414. package/src/server/jobs/runner.spec.ts +213 -0
  415. package/src/server/jobs/runner.ts +213 -0
  416. package/src/server/jobs/timeout.spec.ts +35 -0
  417. package/src/server/jobs/timeout.ts +53 -0
  418. package/src/server/jobs/types.ts +188 -0
  419. package/src/server/master-lock/guard.spec.ts +347 -0
  420. package/src/server/master-lock/guard.ts +290 -0
  421. package/src/server/master-lock/index.ts +44 -0
  422. package/src/server/master-lock/lockPage.spec.ts +88 -0
  423. package/src/server/master-lock/lockPage.ts +313 -0
  424. package/src/server/master-lock/masterLock.spec.ts +338 -0
  425. package/src/server/master-lock/masterLock.ts +627 -0
  426. package/src/server/master-lock/principals.spec.ts +378 -0
  427. package/src/server/master-lock/principals.ts +175 -0
  428. package/src/server/master-lock/seed.spec.ts +69 -0
  429. package/src/server/master-lock/seed.ts +112 -0
  430. package/src/server/master-lock/store.ts +35 -0
  431. package/src/server/media-bun/image.spec.ts +115 -0
  432. package/src/server/media-bun/image.ts +134 -0
  433. package/src/server/media-bun/index.ts +52 -0
  434. package/src/server/media-bun/streaming.spec.ts +134 -0
  435. package/src/server/media-bun/streaming.ts +347 -0
  436. package/src/server/media-bun/video.spec.ts +115 -0
  437. package/src/server/media-bun/video.ts +232 -0
  438. package/src/server/metrics/metricsBuffer.ts +92 -0
  439. package/src/server/metrics/normalizeRoute.spec.ts +51 -0
  440. package/src/server/metrics/normalizeRoute.ts +63 -0
  441. package/src/server/middleware/correlationId.ts +24 -0
  442. package/src/server/middleware/corsAllowlist.spec.ts +118 -0
  443. package/src/server/middleware/corsAllowlist.ts +69 -0
  444. package/src/server/middleware/errorEnvelope.ts +38 -0
  445. package/src/server/middleware/index.ts +19 -0
  446. package/src/server/middleware/localOrigin.spec.ts +168 -0
  447. package/src/server/middleware/localOrigin.ts +139 -0
  448. package/src/server/middleware/rateLimit.spec.ts +72 -0
  449. package/src/server/middleware/rateLimit.ts +125 -0
  450. package/src/server/middleware/requestLogger.ts +95 -0
  451. package/src/server/middleware/securityHeaders.ts +78 -0
  452. package/src/server/middleware/zValidator.spec.ts +251 -0
  453. package/src/server/middleware/zValidator.ts +114 -0
  454. package/src/server/migration/runner.spec.ts +88 -0
  455. package/src/server/migration/runner.ts +87 -0
  456. package/src/server/migration/types.ts +17 -0
  457. package/src/server/net/outboundGuard.spec.ts +90 -0
  458. package/src/server/net/outboundGuard.ts +205 -0
  459. package/src/server/notifications/hub.ts +245 -0
  460. package/src/server/notifications/index.ts +77 -0
  461. package/src/server/notifications/migrations.ts +39 -0
  462. package/src/server/notifications/routes.ts +177 -0
  463. package/src/server/notifications/service.spec.ts +305 -0
  464. package/src/server/notifications/service.ts +112 -0
  465. package/src/server/paths/appDataHome.spec.ts +87 -0
  466. package/src/server/paths/appDataHome.ts +84 -0
  467. package/src/server/private-media/blobRoute.spec.ts +165 -0
  468. package/src/server/private-media/crypto.spec.ts +81 -0
  469. package/src/server/private-media/crypto.ts +155 -0
  470. package/src/server/private-media/gatePolicy.spec.ts +98 -0
  471. package/src/server/private-media/index-store.ts +83 -0
  472. package/src/server/private-media/mountPrivateRoutes.ts +265 -0
  473. package/src/server/private-media/pipeline.spec.ts +111 -0
  474. package/src/server/private-media/pipeline.ts +170 -0
  475. package/src/server/private-media/routes.spec.ts +265 -0
  476. package/src/server/private-media/unlock.ts +112 -0
  477. package/src/server/resume/index.ts +8 -0
  478. package/src/server/resume/resume.spec.ts +118 -0
  479. package/src/server/resume/routes.ts +92 -0
  480. package/src/server/resume/store.ts +82 -0
  481. package/src/server/retention/archive.spec.ts +181 -0
  482. package/src/server/retention/archive.ts +353 -0
  483. package/src/server/retention/fleet.ts +104 -0
  484. package/src/server/retention/index.ts +101 -0
  485. package/src/server/retention/policy.spec.ts +132 -0
  486. package/src/server/retention/policy.ts +392 -0
  487. package/src/server/retention/store.spec.ts +236 -0
  488. package/src/server/retention/store.ts +338 -0
  489. package/src/server/retention/sweeper.spec.ts +321 -0
  490. package/src/server/retention/sweeper.ts +367 -0
  491. package/src/server/retention/target.spec.ts +592 -0
  492. package/src/server/retention/target.ts +613 -0
  493. package/src/server/search/index.ts +12 -0
  494. package/src/server/search/pgSearchProvider.pg.test.ts +392 -0
  495. package/src/server/search/pgSearchProvider.ts +421 -0
  496. package/src/server/search/pgSearchSchema.ts +147 -0
  497. package/src/server/sharing/index.ts +65 -0
  498. package/src/server/sharing/migrations.ts +128 -0
  499. package/src/server/sharing/router.spec.ts +167 -0
  500. package/src/server/sharing/router.ts +194 -0
  501. package/src/server/sharing/sql.ts +109 -0
  502. package/src/server/sharing/store.spec.ts +408 -0
  503. package/src/server/sharing/store.ts +737 -0
  504. package/src/server/sqlite/backup.spec.ts +114 -0
  505. package/src/server/sqlite/backup.ts +154 -0
  506. package/src/server/sqlite/browse.spec.ts +70 -0
  507. package/src/server/sqlite/browse.ts +120 -0
  508. package/src/server/sqlite/export.spec.ts +43 -0
  509. package/src/server/sqlite/export.ts +74 -0
  510. package/src/server/sqlite/fts5.spec.ts +175 -0
  511. package/src/server/sqlite/fts5.ts +255 -0
  512. package/src/server/sqlite/health.spec.ts +79 -0
  513. package/src/server/sqlite/health.ts +105 -0
  514. package/src/server/sqlite/import.spec.ts +75 -0
  515. package/src/server/sqlite/import.ts +141 -0
  516. package/src/server/sqlite/index.ts +64 -0
  517. package/src/server/sqlite/readonlySql.spec.ts +58 -0
  518. package/src/server/sqlite/readonlySql.ts +67 -0
  519. package/src/server/sqlite/stats.spec.ts +21 -0
  520. package/src/server/sqlite/stats.ts +61 -0
  521. package/src/server/sqlite/viewer.spec.ts +127 -0
  522. package/src/server/sqlite/viewer.ts +72 -0
  523. package/src/server/storage/binaryServerProcessing.integration.spec.ts +222 -0
  524. package/src/server/storage/binaryServerProcessing.spec.ts +150 -0
  525. package/src/server/storage/binaryServerProcessing.ts +127 -0
  526. package/src/server/storage/binaryServerStore.ts +102 -0
  527. package/src/server/storage/chunked.integration.spec.ts +185 -0
  528. package/src/server/storage/diskStore.ts +83 -0
  529. package/src/server/storage/files/adapter.photo.display.spec.ts +169 -0
  530. package/src/server/storage/files/adapter.photo.spec.ts +128 -0
  531. package/src/server/storage/files/adapter.spec.ts +121 -0
  532. package/src/server/storage/files/adapter.ts +255 -0
  533. package/src/server/storage/files/catalogue.media-host.spec.ts +184 -0
  534. package/src/server/storage/files/catalogue.orderings.spec.ts +157 -0
  535. package/src/server/storage/files/catalogue.private.spec.ts +106 -0
  536. package/src/server/storage/files/catalogue.recover.spec.ts +131 -0
  537. package/src/server/storage/files/catalogue.sort.spec.ts +154 -0
  538. package/src/server/storage/files/catalogue.spec.ts +133 -0
  539. package/src/server/storage/files/catalogue.trash-import.spec.ts +125 -0
  540. package/src/server/storage/files/catalogue.ts +1326 -0
  541. package/src/server/storage/files/chunkedUpload.spec.ts +111 -0
  542. package/src/server/storage/files/chunkedUpload.ts +146 -0
  543. package/src/server/storage/files/collections.spec.ts +294 -0
  544. package/src/server/storage/files/fileRoutes.replace.spec.ts +88 -0
  545. package/src/server/storage/files/fileRoutes.spec.ts +327 -0
  546. package/src/server/storage/files/fileRoutes.ts +462 -0
  547. package/src/server/storage/files/index.ts +66 -0
  548. package/src/server/storage/files/migrations.ts +187 -0
  549. package/src/server/storage/files/mimeByExt.ts +14 -0
  550. package/src/server/storage/files/stack.spec.ts +258 -0
  551. package/src/server/storage/files/stack.ts +284 -0
  552. package/src/server/storage/files/storageOps.spec.ts +126 -0
  553. package/src/server/storage/files/storageOps.ts +213 -0
  554. package/src/server/storage/files/types.ts +285 -0
  555. package/src/server/storage/imageThumbnail.spec.ts +81 -0
  556. package/src/server/storage/imageThumbnail.ts +60 -0
  557. package/src/server/storage/index.ts +122 -0
  558. package/src/server/storage/mountMediaRoutes.ts +231 -0
  559. package/src/server/storage/objectStore.spec.ts +272 -0
  560. package/src/server/storage/objectStoreMediaStore.ts +63 -0
  561. package/src/server/storage/s3ObjectStore.ts +239 -0
  562. package/src/server/storage/sources.ts +245 -0
  563. package/src/server/storage/storage.spec.ts +219 -0
  564. package/src/server/storage/streamRange.ts +92 -0
  565. package/src/server/storage/streamToken.ts +76 -0
  566. package/src/server/storage/transcode.integration.spec.ts +134 -0
  567. package/src/server/storage/transcodeJobs.spec.ts +152 -0
  568. package/src/server/storage/transcodeJobs.ts +171 -0
  569. package/src/server/storage/types.ts +230 -0
  570. package/src/server/storage/videoDerivativeKeys.spec.ts +112 -0
  571. package/src/server/storage/videoDerivativeKeys.ts +172 -0
  572. package/src/server/storage/videoProcessor.posterOnly.spec.ts +106 -0
  573. package/src/server/storage/videoProcessor.ts +229 -0
  574. package/src/server/sync/alarm.spec.ts +149 -0
  575. package/src/server/sync/alarm.ts +137 -0
  576. package/src/server/sync/commands.spec.ts +145 -0
  577. package/src/server/sync/commands.ts +361 -0
  578. package/src/server/sync/engine.spec.ts +496 -0
  579. package/src/server/sync/engine.ts +255 -0
  580. package/src/server/sync/http.ts +316 -0
  581. package/src/server/sync/httpRemote.spec.ts +158 -0
  582. package/src/server/sync/index.ts +90 -0
  583. package/src/server/sync/opLog.spec.ts +110 -0
  584. package/src/server/sync/opLog.ts +189 -0
  585. package/src/server/sync/planner.spec.ts +53 -0
  586. package/src/server/sync/planner.ts +62 -0
  587. package/src/server/sync/status.spec.ts +92 -0
  588. package/src/server/sync/status.ts +108 -0
  589. package/src/server/sync/timer.spec.ts +150 -0
  590. package/src/server/sync/timer.ts +207 -0
  591. package/src/server/sync/tokens.spec.ts +38 -0
  592. package/src/server/sync/tokens.ts +94 -0
  593. package/src/server/sync/types.ts +108 -0
  594. package/src/server/ws/eventBus.spec.ts +67 -0
  595. package/src/server/ws/eventBus.ts +46 -0
  596. package/src/server/ws/hub.integration.spec.ts +93 -0
  597. package/src/server/ws/hub.spec.ts +282 -0
  598. package/src/server/ws/hub.ts +168 -0
  599. package/src/server/ws/index.ts +20 -0
  600. package/src/server/ws/presence.spec.ts +27 -0
  601. package/src/server/ws/presence.ts +26 -0
  602. package/src/server/ws/room.spec.ts +36 -0
  603. package/src/server/ws/room.ts +29 -0
  604. package/src/server/ws/types.ts +134 -0
  605. package/src/skippedTestsAreAnswered.spec.ts +215 -0
  606. package/src/testTmpRoot.spec.ts +102 -0
package/package.json ADDED
@@ -0,0 +1,234 @@
1
+ {
2
+ "name": "cursedbelt-server",
3
+ "version": "1.0.0",
4
+ "license": "ISC",
5
+ "type": "module",
6
+ "description": "The app-facing Bun/Hono server tier of the cursedbelt split — storage, sharing, activity, guard, sync. React-free; cursedbelt-core below it.",
7
+ "cursed": {
8
+ "schemaVersion": 1,
9
+ "app": {
10
+ "name": "cursedbelt-server",
11
+ "commands": {
12
+ "test": "test",
13
+ "typecheck": "typecheck",
14
+ "build": "build"
15
+ }
16
+ }
17
+ },
18
+ "scripts": {
19
+ "clean": "rm -rf dist",
20
+ "typecheck": "tsc -p tsconfig.build.json --noEmit",
21
+ "test": "NODE_ENV=development bun test src",
22
+ "build": "bun run clean && tsc -p tsconfig.build.json",
23
+ "paths": "bun ../../tools/check-paths.ts .",
24
+ "verify": "bun run paths && bun run typecheck && bun run build && bun run test",
25
+ "prepublishOnly": "bun run verify"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "src"
30
+ ],
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/server/index.d.ts",
34
+ "bun": "./src/server/index.ts",
35
+ "source": "./src/server/index.ts",
36
+ "import": "./dist/server/index.js"
37
+ },
38
+ "./activity": {
39
+ "types": "./dist/server/activity/index.d.ts",
40
+ "bun": "./src/server/activity/index.ts",
41
+ "source": "./src/server/activity/index.ts",
42
+ "import": "./dist/server/activity/index.js"
43
+ },
44
+ "./context": {
45
+ "types": "./dist/server/context.d.ts",
46
+ "bun": "./src/server/context.ts",
47
+ "source": "./src/server/context.ts",
48
+ "import": "./dist/server/context.js"
49
+ },
50
+ "./dropzone": {
51
+ "types": "./dist/server/dropzone/index.d.ts",
52
+ "bun": "./src/server/dropzone/index.ts",
53
+ "source": "./src/server/dropzone/index.ts",
54
+ "import": "./dist/server/dropzone/index.js"
55
+ },
56
+ "./errors": {
57
+ "types": "./dist/server/errors.d.ts",
58
+ "bun": "./src/server/errors.ts",
59
+ "source": "./src/server/errors.ts",
60
+ "import": "./dist/server/errors.js"
61
+ },
62
+ "./guard": {
63
+ "types": "./dist/server/guard/index.d.ts",
64
+ "bun": "./src/server/guard/index.ts",
65
+ "source": "./src/server/guard/index.ts",
66
+ "import": "./dist/server/guard/index.js"
67
+ },
68
+ "./guard/revocations": {
69
+ "types": "./dist/server/guard/revocationStore.d.ts",
70
+ "bun": "./src/server/guard/revocationStore.ts",
71
+ "source": "./src/server/guard/revocationStore.ts",
72
+ "import": "./dist/server/guard/revocationStore.js"
73
+ },
74
+ "./incidents": {
75
+ "types": "./dist/server/incidents/index.d.ts",
76
+ "bun": "./src/server/incidents/index.ts",
77
+ "source": "./src/server/incidents/index.ts",
78
+ "import": "./dist/server/incidents/index.js"
79
+ },
80
+ "./item-crypto": {
81
+ "types": "./dist/server/auth/vault.d.ts",
82
+ "bun": "./src/server/auth/vault.ts",
83
+ "source": "./src/server/auth/vault.ts",
84
+ "import": "./dist/server/auth/vault.js"
85
+ },
86
+ "./jobs": {
87
+ "types": "./dist/server/jobs/index.d.ts",
88
+ "bun": "./src/server/jobs/index.ts",
89
+ "source": "./src/server/jobs/index.ts",
90
+ "import": "./dist/server/jobs/index.js"
91
+ },
92
+ "./login-throttle": {
93
+ "types": "./dist/server/auth/loginThrottle.d.ts",
94
+ "bun": "./src/server/auth/loginThrottle.ts",
95
+ "source": "./src/server/auth/loginThrottle.ts",
96
+ "import": "./dist/server/auth/loginThrottle.js"
97
+ },
98
+ "./master-lock": {
99
+ "types": "./dist/server/master-lock/index.d.ts",
100
+ "bun": "./src/server/master-lock/index.ts",
101
+ "source": "./src/server/master-lock/index.ts",
102
+ "import": "./dist/server/master-lock/index.js"
103
+ },
104
+ "./middleware": {
105
+ "types": "./dist/server/middleware/index.d.ts",
106
+ "bun": "./src/server/middleware/index.ts",
107
+ "source": "./src/server/middleware/index.ts",
108
+ "import": "./dist/server/middleware/index.js"
109
+ },
110
+ "./migration": {
111
+ "types": "./dist/server/migration/runner.d.ts",
112
+ "bun": "./src/server/migration/runner.ts",
113
+ "source": "./src/server/migration/runner.ts",
114
+ "import": "./dist/server/migration/runner.js"
115
+ },
116
+ "./net": {
117
+ "types": "./dist/server/net/outboundGuard.d.ts",
118
+ "bun": "./src/server/net/outboundGuard.ts",
119
+ "source": "./src/server/net/outboundGuard.ts",
120
+ "import": "./dist/server/net/outboundGuard.js"
121
+ },
122
+ "./notifications": {
123
+ "types": "./dist/server/notifications/index.d.ts",
124
+ "bun": "./src/server/notifications/index.ts",
125
+ "source": "./src/server/notifications/index.ts",
126
+ "import": "./dist/server/notifications/index.js"
127
+ },
128
+ "./resume": {
129
+ "types": "./dist/server/resume/index.d.ts",
130
+ "bun": "./src/server/resume/index.ts",
131
+ "source": "./src/server/resume/index.ts",
132
+ "import": "./dist/server/resume/index.js"
133
+ },
134
+ "./retention": {
135
+ "types": "./dist/server/retention/index.d.ts",
136
+ "bun": "./src/server/retention/index.ts",
137
+ "source": "./src/server/retention/index.ts",
138
+ "import": "./dist/server/retention/index.js"
139
+ },
140
+ "./search": {
141
+ "types": "./dist/server/search/index.d.ts",
142
+ "bun": "./src/server/search/index.ts",
143
+ "source": "./src/server/search/index.ts",
144
+ "import": "./dist/server/search/index.js"
145
+ },
146
+ "./sharing": {
147
+ "types": "./dist/server/sharing/index.d.ts",
148
+ "bun": "./src/server/sharing/index.ts",
149
+ "source": "./src/server/sharing/index.ts",
150
+ "import": "./dist/server/sharing/index.js"
151
+ },
152
+ "./sqlite": {
153
+ "types": "./dist/server/sqlite/index.d.ts",
154
+ "bun": "./src/server/sqlite/index.ts",
155
+ "source": "./src/server/sqlite/index.ts",
156
+ "import": "./dist/server/sqlite/index.js"
157
+ },
158
+ "./storage": {
159
+ "types": "./dist/server/storage/index.d.ts",
160
+ "bun": "./src/server/storage/index.ts",
161
+ "source": "./src/server/storage/index.ts",
162
+ "import": "./dist/server/storage/index.js"
163
+ },
164
+ "./storage/types": {
165
+ "types": "./dist/server/storage/types.d.ts",
166
+ "bun": "./src/server/storage/types.ts",
167
+ "source": "./src/server/storage/types.ts",
168
+ "import": "./dist/server/storage/types.js"
169
+ },
170
+ "./sync": {
171
+ "types": "./dist/server/sync/index.d.ts",
172
+ "bun": "./src/server/sync/index.ts",
173
+ "source": "./src/server/sync/index.ts",
174
+ "import": "./dist/server/sync/index.js"
175
+ },
176
+ "./ws": {
177
+ "types": "./dist/server/ws/index.d.ts",
178
+ "bun": "./src/server/ws/index.ts",
179
+ "source": "./src/server/ws/index.ts",
180
+ "import": "./dist/server/ws/index.js"
181
+ }
182
+ },
183
+ "dependencies": {
184
+ "cursedbelt-core": "^1.0.0",
185
+ "cwip": "^3.0.2",
186
+ "jose": "^6.2.3"
187
+ },
188
+ "peerDependencies": {
189
+ "hono": ">=4",
190
+ "zod": "^4.4.0",
191
+ "@node-rs/argon2": "^2.0.2",
192
+ "kysely": "^0.28.17",
193
+ "kysely-bun-sqlite": "^0.4.0",
194
+ "otplib": "^13.4.1",
195
+ "plainjob": "^0.0.14",
196
+ "sharp": "^0.35.2"
197
+ },
198
+ "peerDependenciesMeta": {
199
+ "@node-rs/argon2": {
200
+ "optional": true
201
+ },
202
+ "kysely": {
203
+ "optional": true
204
+ },
205
+ "kysely-bun-sqlite": {
206
+ "optional": true
207
+ },
208
+ "otplib": {
209
+ "optional": true
210
+ },
211
+ "plainjob": {
212
+ "optional": true
213
+ },
214
+ "sharp": {
215
+ "optional": true
216
+ }
217
+ },
218
+ "devDependencies": {
219
+ "@biomejs/biome": "^2.5.0",
220
+ "@happy-dom/global-registrator": "^20.10.6",
221
+ "@node-rs/argon2": "^2.0.2",
222
+ "@types/bun": "^1.3.14",
223
+ "@types/node": "^24",
224
+ "hono": "4.12.28",
225
+ "kysely": "^0.28.17",
226
+ "kysely-bun-sqlite": "^0.4.0",
227
+ "otplib": "^13.4.1",
228
+ "papaparse": "^5",
229
+ "plainjob": "^0.0.14",
230
+ "sharp": "^0.35.2",
231
+ "typescript": "^6.0.3",
232
+ "zod": "4.4.3"
233
+ }
234
+ }
@@ -0,0 +1,87 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import pkg from '../package.json';
3
+
4
+ /**
5
+ * Every declared dependency must be reachable from an import (2026-09-13).
6
+ *
7
+ * `dependencies` is not advice — a consumer installs all of it to render one
8
+ * button. `peerDependencies` is a promise that installing the peer lights a
9
+ * feature up. Both rot silently: a component gets deleted, its package stays
10
+ * declared, and nothing anywhere reds. At the time this was written the manifest
11
+ * carried three runtime deps and five optional peers that no file imported.
12
+ *
13
+ * 🔴 The reason this matches an IMPORT SPECIFIER and scans EVERY file type,
14
+ * rather than grepping .ts for the bare name:
15
+ *
16
+ * - A .ts-only grep says `tw-animate-css` is dead. It is not — it is pulled in
17
+ * from CSS (`@import` in src/styles.css), and deleting it would have shipped
18
+ * a package whose stylesheet cannot resolve. That is the exact mistake this
19
+ * session made on its first pass.
20
+ * - A bare-name grep says everything is alive, because names like `diff` and
21
+ * `marked` appear in prose in hundreds of files. A gate that cannot fail is
22
+ * not a gate.
23
+ *
24
+ * devDependencies are deliberately NOT checked: several are installed only so
25
+ * this repo can typecheck and test an OPTIONAL peer's integration, so "nothing
26
+ * imports it by name" is the expected state there, not a defect.
27
+ */
28
+ const ROOTS = ['src', 'scripts'] as const;
29
+
30
+ // Reading a font or a screenshot as text costs time and can never match.
31
+ const BINARY = /\.(png|jpe?g|gif|webp|avif|ico|mp4|webm|mp3|wav|pdf|zip|gz|woff2?|ttf|otf|eot|wasm)$/i;
32
+
33
+ /**
34
+ * `from 'x'` · `import 'x/y.css'` · `import('x')` · `require('x')` · `@import "x"`,
35
+ * with or without a subpath. Anchored on the specifier quote so a name mentioned
36
+ * in prose or in a comment does not count as a use.
37
+ */
38
+ const RE_SPECIAL = /[.*+?^${}()|[\]\\]/g;
39
+
40
+ const importsPackage = (name: string): RegExp =>
41
+ new RegExp(`(?:from|import|require|@import)\\s*\\(?\\s*['"]${name.replace(RE_SPECIAL, '\\$&')}(?:/[^'"]*)?['"]`);
42
+
43
+ // 🔴 Bun.Glob + Bun.file, NOT node:fs — this package's test preload virtualizes
44
+ // node:fs, so a readdirSync/readFileSync scan reads MOCK data and passes against
45
+ // files it never opened. Same trap as publishShape.spec.ts; see its header.
46
+ let cache: Promise<string[]> | undefined;
47
+ const sources = (): Promise<string[]> => {
48
+ cache ??= (async () => {
49
+ const repo = `${import.meta.dir}/..`;
50
+ const texts: string[] = [];
51
+ for (const root of ROOTS) {
52
+ const dir = `${repo}/${root}`;
53
+ for (const rel of new Bun.Glob('**/*').scanSync({ cwd: dir, onlyFiles: true })) {
54
+ if (BINARY.test(rel)) continue;
55
+ texts.push(await Bun.file(`${dir}/${rel}`).text());
56
+ }
57
+ }
58
+ return texts;
59
+ })();
60
+ return cache;
61
+ };
62
+
63
+ const unimported = async (block: Record<string, string> | undefined): Promise<string[]> => {
64
+ const texts = await sources();
65
+ return Object.keys(block ?? {}).filter((name) => {
66
+ const re = importsPackage(name);
67
+ return !texts.some((t) => re.test(t));
68
+ });
69
+ };
70
+
71
+ describe('declared dependencies are imported', () => {
72
+ it('has scanned a real source tree', async () => {
73
+ // Guards the whole file: if the glob or the fs mock ever returns nothing,
74
+ // every assertion below passes vacuously and the gate quietly dies.
75
+ expect((await sources()).length).toBeGreaterThan(100);
76
+ });
77
+
78
+ for (const field of ['dependencies', 'peerDependencies'] as const) {
79
+ it(`${field} names nothing the code never imports`, async () => {
80
+ const dead = await unimported((pkg as Record<string, unknown>)[field] as Record<string, string>);
81
+ expect(
82
+ dead,
83
+ `declared in ${field} but imported nowhere in ${ROOTS.join('/')} — import it or drop it:\n ${dead.join('\n ')}`,
84
+ ).toEqual([]);
85
+ });
86
+ }
87
+ });
@@ -0,0 +1,358 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { readdirSync, rmSync, statSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import pkg from '../package.json';
5
+
6
+ /**
7
+ * A LEAF subpath's whole promise is what it does NOT pull in. Nothing in this repo
8
+ * measured that until now (2026-09-15), so the promise was kept by hand — and it was
9
+ * broken twice in two days, in the same shape, one level apart.
10
+ *
11
+ * ## The measurement this exists because of
12
+ *
13
+ * `apps/collections/src/kit/binaryStore.ts` needed exactly one thing from here:
14
+ *
15
+ * import type { FileTokenClaims } from "cursedbelt/server/storage";
16
+ *
17
+ * A TYPE — TypeScript erases it, so the app should have paid nothing at runtime. What it
18
+ * actually paid was:
19
+ *
20
+ * error: Cannot find package 'otplib' from
21
+ * …/node_modules/cursedbelt/src/server/auth/totp.ts
22
+ *
23
+ * …and four unrelated route suites died before anything was measured. `server/storage`'s
24
+ * index is a barrel; the barrel reached `streamToken.ts`, which imported the `../auth`
25
+ * INDEX for two jose functions, and that index reaches `totp.ts` → `otplib`, an optional
26
+ * peer. (`sessionStore.ts` takes its Kysely db as a TYPE, so the `kysely` half of the same
27
+ * trap arrives through the `./server` barrel's `db/kysely.ts` instead — measured, not
28
+ * assumed: bundling `./server/storage` externals before this change listed `otplib` and
29
+ * `hono/cookie`, never `kysely`.) The app declared `otplib` as a direct dependency to get
30
+ * its route suites back — a one-time-password library installed to satisfy a claim shape.
31
+ *
32
+ * That is the exact shape 2.5.1 shipped `./server/login-throttle` to fix, one level
33
+ * deeper, and the rule written down after it ("never import the `cursedbelt/server`
34
+ * barrel for one primitive") could not catch it, because `./server/storage` IS a leaf by
35
+ * that rule's standard and has a barrel of its own. A rule that only a human can apply
36
+ * gets re-broken by the next module that looks like a leaf. So: a check.
37
+ *
38
+ * ## What it does
39
+ *
40
+ * Assembles a throwaway consumer under `$TMPDIR` — a `node_modules/cursedbelt` holding
41
+ * this package's REAL package.json (so the real `exports` map is what resolves) and
42
+ * nothing else but the leaf source files themselves — then spawns bun in it and imports
43
+ * each leaf by its PUBLIC specifier. No peers are installed, no other file of this package
44
+ * is even on disk, so any import that survives transpilation fails the import and this
45
+ * spec with it. `import type` is erased and costs nothing, which is the whole point:
46
+ * `verbatimModuleSyntax` is on, so a type import that is not written `import type` is
47
+ * already a typecheck error, and source and `dist` therefore carry the same module graph.
48
+ *
49
+ * ## 🔴 The trap that makes the naive version of this check a lie
50
+ *
51
+ * Bun AUTO-INSTALLS a missing bare import out of `~/.bun/install/cache` when the walk up
52
+ * from the importing file finds NO `node_modules` at all. Measured while building this, in
53
+ * a scratch directory holding two files and nothing else: `import { authenticator } from
54
+ * 'otplib'` resolved — from
55
+ * `~/.bun/install/cache/otplib@13.5.0@@@1/dist/index.js` — and the only error was a missing
56
+ * named export. An "empty fixture" therefore proves NOTHING about what a leaf drags: every
57
+ * peer in the cache answers.
58
+ *
59
+ * Two things hold the line, and the second is the one that matters:
60
+ *
61
+ * 1. `bunfig.toml` with `[install] auto = "disable"` in the fixture root. Note what this
62
+ * is and is not: with a `node_modules/` present (as here) bun does not auto-install
63
+ * anyway — removing the line and re-running left the negative control failing exactly
64
+ * as before. It is the second lock, for the day this fixture is refactored into one
65
+ * that has no `node_modules` and the trap silently comes back.
66
+ * 2. The NEGATIVE CONTROL: a file importing `otplib` and nothing else is copied in beside
67
+ * the leaves, and this spec fails if importing it SUCCEEDS. Whatever makes peers
68
+ * resolvable — auto-install, a `node_modules` above the scratch root, a future bun
69
+ * default — the control sees it and reds, instead of letting every assertion below
70
+ * pass vacuously.
71
+ *
72
+ * ## 🔴 Verified failing, 2026-09-15, before it was trusted — every branch
73
+ *
74
+ * · `import 'otplib'` added to `src/server/storage/types.ts`
75
+ * → "cursedbelt/server/storage/types must import nothing at runtime … Cannot find
76
+ * package 'otplib' imported from …/node_modules/cursedbelt/src/server/storage/types.ts"
77
+ * · the same, but `import { createStreamTokenService } from './streamToken'` — a
78
+ * relative import of a module inside this package
79
+ * → red too: "Cannot find module './streamToken'". A leaf may not reach sideways
80
+ * either, which is why ONLY the leaf files are copied into the fixture.
81
+ * · `./server/storage/types` re-pointed at `src/server/storage/index.ts`, the barrel it
82
+ * was split out of
83
+ * → red: "Cannot find module './videoDerivativeKeys'". A barrel cannot pass this.
84
+ * · the negative control re-pointed at `loginThrottle.ts`, which imports nothing, so the
85
+ * fixture stopped demonstrating that peers are unreachable
86
+ * → red on the control itself: "the fixture resolved 'otplib' … Every assertion below
87
+ * is vacuous until that is fixed". The vacuity guard fires.
88
+ * · `src/server/private-media/unlock.ts` put back to `import … from '../auth'` — the
89
+ * second, two-hop edge, which grep for `../auth` inside `src/server/storage` cannot see
90
+ * → red: "importing cursedbelt/server/storage statically pulls these OPTIONAL peers
91
+ * … + otplib". This is the branch that found that edge in the first place.
92
+ */
93
+
94
+ const REPO = fileURLToPath(new URL('..', import.meta.url));
95
+
96
+ /**
97
+ * Every subpath that promises to cost a consumer NOTHING at runtime. A leaf earns its
98
+ * place here by being the answer to "I want one type / one primitive out of a module
99
+ * whose index is heavy" — the entry names the runtime symbol proving the module really
100
+ * evaluated, so an accidentally-empty module can never pass this vacuously.
101
+ *
102
+ * The file is read from `exports`, never hard-coded: re-target the subpath and the check
103
+ * follows it to the new file rather than going quietly green against the old one.
104
+ */
105
+ const LEAVES = [
106
+ {
107
+ subpath: './storage/types',
108
+ /** Claim/config shapes + the keyspace helpers. apps/collections wants `FileTokenClaims`. */
109
+ evaluates: 'fsSourceKey',
110
+ },
111
+ {
112
+ subpath: './login-throttle',
113
+ /** The failed-login backoff. Every app with a login door; shipped as 2.5.1. */
114
+ evaluates: 'createLoginThrottle',
115
+ },
116
+ ] as const;
117
+
118
+ /**
119
+ * Imports `otplib` and nothing else, so its failure message is unambiguous. It is the
120
+ * proof that the fixture has no peers — not an assertion about `totp.ts` itself.
121
+ */
122
+ const CONTROL = 'src/server/auth/totp.ts';
123
+
124
+ type Outcome = { ok: true; keys: string[] } | { ok: false; error: string };
125
+
126
+ const exportsMap = pkg.exports as Record<string, { bun?: string } | string>;
127
+
128
+ /** `./src/server/storage/types.ts` → `src/server/storage/types.ts`. */
129
+ const sourceOf = (subpath: string): string => {
130
+ const entry = exportsMap[subpath];
131
+ const bun = typeof entry === 'object' && entry !== null ? entry.bun : undefined;
132
+ if (typeof bun !== 'string') {
133
+ throw new Error(`package.json exports has no \`bun\` target for "${subpath}"`);
134
+ }
135
+ return bun.replace(/^\.\//, '');
136
+ };
137
+
138
+ /**
139
+ * 🔴 The fixture must sit OUTSIDE this repo, and where it lands is not a detail.
140
+ *
141
+ * `scripts/testTmpRoot.ts` redirects `$TMPDIR` per process, and when `$FORGE_STATE`
142
+ * is unset — a bare checkout with no generation around it — its fallback is
143
+ * deliberately repo-local: `<repo>/.agent.noindex/tmp/<pid>`. For every other suite
144
+ * that is exactly right. For this one it is fatal: bun resolves a bare import by
145
+ * walking node_modules UP to the filesystem root, so a fixture under the repo finds
146
+ * `<repo>/node_modules/otplib` and every peer this check exists to prove unreachable
147
+ * becomes reachable.
148
+ *
149
+ * Measured 2026-09-15: with `$FORGE_STATE` set the negative control failed correctly;
150
+ * with it unset the SAME control resolved `otplib` out of this repo's own
151
+ * `node_modules` and the guard fired — *"the fixture resolved 'otplib' … Every
152
+ * assertion below is vacuous until that is fixed"*. So `bun run verify` was green
153
+ * under the runner and red in a plain shell, for a reason that has nothing to do with
154
+ * the code under test. The control did its job; the fixture's address was the bug.
155
+ *
156
+ * Resolution here is therefore explicit rather than inherited. The redirected root is
157
+ * used when it lies outside the repo (the normal case — the runner always sets
158
+ * `$FORGE_STATE`, and the preload's sweep then cleans up after a killed run). When it
159
+ * does not, this hops to `$HOME`, which `resolveTestTmpRoot` refuses for the general
160
+ * default and which this check genuinely requires: an isolated root is the whole
161
+ * measurement. Stale siblings are swept by mtime, the same way the preload does it,
162
+ * so the hop cannot accumulate.
163
+ */
164
+ const REPO_PREFIX = `${REPO.replace(/\/$/, '')}/`;
165
+
166
+ const fixtureRoot = (): string => {
167
+ const redirected = process.env.TMPDIR;
168
+ if (redirected !== undefined && !`${redirected}/`.startsWith(REPO_PREFIX)) {
169
+ return `${redirected}/leaf-subpath-fixture`;
170
+ }
171
+ const home = process.env.HOME?.trim();
172
+ if (home === undefined || home === '') {
173
+ throw new Error(
174
+ 'no isolated root available for the leaf fixture ($TMPDIR is inside this repo and $HOME is unset) — ' +
175
+ 'a check that cannot isolate itself is not a passing check',
176
+ );
177
+ }
178
+ const outside = `${home}/.${pkg.name}-leaf-fixture.noindex`;
179
+ try {
180
+ const cutoff = Date.now() - 6 * 60 * 60 * 1000;
181
+ for (const entry of readdirSync(outside)) {
182
+ const path = `${outside}/${entry}`;
183
+ try {
184
+ if (statSync(path).mtimeMs < cutoff) rmSync(path, { recursive: true, force: true });
185
+ } catch {
186
+ // racing another run's sweep is fine — whoever wins, it goes
187
+ }
188
+ }
189
+ } catch {
190
+ // no root yet: Bun.write creates it below
191
+ }
192
+ return `${outside}/${process.pid}/leaf-subpath-fixture`;
193
+ };
194
+
195
+ const run = async (): Promise<Record<string, Outcome>> => {
196
+ const root = fixtureRoot();
197
+ const pkgDir = `${root}/node_modules/${pkg.name}`;
198
+
199
+ // The second lock against bun's auto-install (see the header). The negative control is the
200
+ // first one, and the one that would catch this line being wrong.
201
+ await Bun.write(`${root}/bunfig.toml`, '[install]\nauto = "disable"\n');
202
+ // The REAL manifest: the export map under test, resolved exactly as a consumer resolves it.
203
+ await Bun.write(`${pkgDir}/package.json`, Bun.file(`${REPO}/package.json`));
204
+
205
+ const targets: Array<{ name: string; specifier: string }> = [];
206
+ for (const leaf of LEAVES) {
207
+ const source = sourceOf(leaf.subpath);
208
+ // 🔴 Bun.file/Bun.write, NOT node:fs — this repo's test preload virtualizes node:fs, so a
209
+ // copy made through it can land in a mock the spawned child cannot see. Same trap as
210
+ // publishShape.spec.ts.
211
+ await Bun.write(`${pkgDir}/${source}`, Bun.file(`${REPO}/${source}`));
212
+ targets.push({ name: leaf.subpath, specifier: `${pkg.name}/${leaf.subpath.slice(2)}` });
213
+ }
214
+ await Bun.write(`${pkgDir}/${CONTROL}`, Bun.file(`${REPO}/${CONTROL}`));
215
+ // By PATH, not by subpath: the control is deliberately not exported, and an
216
+ // ERR_PACKAGE_PATH_NOT_EXPORTED would prove nothing about peer resolution.
217
+ targets.push({ name: 'control', specifier: `./node_modules/${pkg.name}/${CONTROL}` });
218
+
219
+ await Bun.write(
220
+ `${root}/entry.ts`,
221
+ `const targets = ${JSON.stringify(targets)};
222
+ const out = {};
223
+ for (const t of targets) {
224
+ try {
225
+ const mod = await import(t.specifier);
226
+ out[t.name] = { ok: true, keys: Object.keys(mod) };
227
+ } catch (error) {
228
+ out[t.name] = { ok: false, error: String((error && error.message) || error) };
229
+ }
230
+ }
231
+ console.log(JSON.stringify(out));
232
+ `,
233
+ );
234
+
235
+ const child = Bun.spawnSync(['bun', 'run', 'entry.ts'], {
236
+ cwd: root,
237
+ stdout: 'pipe',
238
+ stderr: 'pipe',
239
+ });
240
+ const stdout = child.stdout.toString().trim();
241
+ if (child.exitCode !== 0 || stdout === '') {
242
+ throw new Error(
243
+ `the fixture could not run at all (exit ${child.exitCode}) — that is a broken check, not a passing one:\n${child.stderr.toString()}`,
244
+ );
245
+ }
246
+ return JSON.parse(stdout) as Record<string, Outcome>;
247
+ };
248
+
249
+ /**
250
+ * The other half, and the one that caught the SECOND edge. A leaf can be clean while the
251
+ * barrel it was split out of still drags an optional peer, and a barrel is what most apps
252
+ * import — `music`, `family` and `roms` all take `cursedbelt/server/storage` whole.
253
+ *
254
+ * Measured by bundling the subpath's relative graph with every bare import left external
255
+ * and reading what remains. The subpaths listed must reach NO optional peer with a STATIC
256
+ * import: a static one is paid at import time by every consumer, which is the crash the
257
+ * task above is about; a `await import('sharp')` inside the function that needs it is
258
+ * exactly the right shape and stays legal here.
259
+ *
260
+ * Limitation, stated rather than hidden: the externals are read out of the bundle's import
261
+ * statements textually, so an import bun emits across several lines would be missed. That
262
+ * makes this half a floor, not a ceiling — the runtime fixture above is the strict one.
263
+ */
264
+ const NO_STATIC_OPTIONAL_PEERS = [
265
+ {
266
+ subpath: './storage',
267
+ /** Its `streamToken.ts` and (two hops out) `private-media/unlock.ts` both imported the
268
+ * `../auth` index for two jose functions, so `otplib` was static in here until 2.6.0. */
269
+ entry: 'src/server/storage/index.ts',
270
+ },
271
+ ] as const;
272
+
273
+ const OPTIONAL_PEERS = new Set(
274
+ Object.entries(
275
+ (pkg as { peerDependenciesMeta?: Record<string, { optional?: boolean }> })
276
+ .peerDependenciesMeta ?? {},
277
+ )
278
+ .filter(([, meta]) => meta?.optional === true)
279
+ .map(([name]) => name),
280
+ );
281
+
282
+ /** `import x from "pkg"`, `import "pkg"`, `export … from "pkg"` — one line each, as bun emits. */
283
+ const STATIC_SPECIFIER = /^(?:import|export)\s[^\n]*?["']([^"'\n]+)["'];?$|^import\s*["']([^"'\n]+)["'];?$/gm;
284
+
285
+ const staticOptionalPeersOf = (entry: string): string[] => {
286
+ const build = Bun.spawnSync(
287
+ ['bun', 'build', entry, '--target=bun', '--packages=external'],
288
+ { cwd: REPO, stdout: 'pipe', stderr: 'pipe' },
289
+ );
290
+ const bundle = build.stdout.toString();
291
+ if (build.exitCode !== 0 || bundle.trim() === '') {
292
+ throw new Error(
293
+ `could not bundle ${entry} (exit ${build.exitCode}) — a check that cannot measure is not a passing check:\n${build.stderr.toString()}`,
294
+ );
295
+ }
296
+ const found = new Set<string>();
297
+ for (const match of bundle.matchAll(STATIC_SPECIFIER)) {
298
+ const specifier = match[1] ?? match[2];
299
+ if (specifier === undefined || specifier.startsWith('.')) continue;
300
+ // `@scope/name/deep` → `@scope/name`, `pkg/deep` → `pkg`.
301
+ const parts = specifier.split('/');
302
+ const name = specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
303
+ if (name !== undefined && OPTIONAL_PEERS.has(name)) found.add(name);
304
+ }
305
+ return [...found].sort();
306
+ };
307
+
308
+ const outcomes = await run();
309
+
310
+ describe('leaf subpaths import nothing at runtime', () => {
311
+ it('has a fixture with no peers installed (negative control)', () => {
312
+ const control = outcomes.control;
313
+ expect(control, 'the control never ran — the fixture is not measuring anything').toBeDefined();
314
+ expect(
315
+ control?.ok === false,
316
+ `the fixture resolved 'otplib' — bun auto-installed it out of ~/.bun/install/cache, or a node_modules above the fixture answered. Every assertion below is vacuous until that is fixed; do not delete this test to make it pass.`,
317
+ ).toBe(true);
318
+ expect(
319
+ control?.ok === false ? control.error : '',
320
+ 'the control failed for the wrong reason — it must fail on the missing PACKAGE',
321
+ ).toContain("Cannot find package 'otplib'");
322
+ });
323
+
324
+ for (const leaf of LEAVES) {
325
+ it(`${pkg.name}/${leaf.subpath.slice(2)} imports clean`, () => {
326
+ const outcome = outcomes[leaf.subpath];
327
+ expect(outcome, `${leaf.subpath} was never imported by the fixture`).toBeDefined();
328
+ expect(
329
+ outcome?.ok === true ? '' : outcome?.ok === false ? outcome.error : 'missing',
330
+ `${pkg.name}/${leaf.subpath.slice(2)} must import NOTHING at runtime — that is the entire reason the subpath exists. Move whatever it now reaches behind \`import type\`, or split the leaf again; do not add the dependency to a consumer.`,
331
+ ).toBe('');
332
+ // Non-vacuity: a module that resolved but exported nothing would otherwise pass.
333
+ expect(
334
+ outcome?.ok === true ? outcome.keys : [],
335
+ `${leaf.subpath} resolved but does not export ${leaf.evaluates} — the check is pointing at the wrong file`,
336
+ ).toContain(leaf.evaluates);
337
+ });
338
+ }
339
+ });
340
+
341
+ describe('barrels reach no optional peer statically', () => {
342
+ it('knows which peers are optional', () => {
343
+ // Guards the assertions below: an empty set makes every one of them pass vacuously.
344
+ expect(OPTIONAL_PEERS.size, 'peerDependenciesMeta lists no optional peer').toBeGreaterThan(3);
345
+ expect([...OPTIONAL_PEERS], 'otplib is the peer this whole spec was written for').toContain(
346
+ 'otplib',
347
+ );
348
+ });
349
+
350
+ for (const target of NO_STATIC_OPTIONAL_PEERS) {
351
+ it(`${pkg.name}/${target.subpath.slice(2)} costs a consumer no optional peer to import`, () => {
352
+ expect(
353
+ staticOptionalPeersOf(target.entry),
354
+ `importing ${pkg.name}/${target.subpath.slice(2)} statically pulls these OPTIONAL peers, so every consumer must install them for code it may never call. Either import the leaf module that has what you need instead of a sibling INDEX (that is how 'otplib' got in here twice), or make the dependency lazy: \`const { x } = await import('pkg')\` inside the function that needs it.`,
355
+ ).toEqual([]);
356
+ });
357
+ }
358
+ });