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
@@ -0,0 +1,79 @@
1
+ // ONE shared append-only table backs every namespace's audit trail — not a
2
+ // shadow table per business table. cursedshell's `defineService` mutations
3
+ // are dispatched against host-injected Store interfaces (`NotesStore`,
4
+ // `AliasStore`, …), never raw SQL the host's DB owns, so there is no single
5
+ // business table a `CREATE TRIGGER` could attach to. `(namespace, target_id)`
6
+ // plays the role a per-table shadow table would: history for cursedshell's
7
+ // `todo` plugin and an app's own `todo` table can coexist without collision.
8
+ export const AUDIT_LOG_MIGRATIONS = [
9
+ {
10
+ name: '0001_audit_log',
11
+ up(db) {
12
+ db.run(`
13
+ CREATE TABLE IF NOT EXISTS audit_log (
14
+ audit_id INTEGER PRIMARY KEY AUTOINCREMENT,
15
+ namespace TEXT NOT NULL,
16
+ mutation_key TEXT NOT NULL,
17
+ target_id TEXT NOT NULL,
18
+ version_key INTEGER NOT NULL,
19
+ operation TEXT NOT NULL CHECK (operation IN ('insert', 'update', 'delete')),
20
+ tenant_id TEXT NOT NULL,
21
+ changed_by TEXT,
22
+ changed_at TEXT NOT NULL,
23
+ snapshot_data TEXT,
24
+ UNIQUE(tenant_id, namespace, target_id, version_key)
25
+ )
26
+ `);
27
+ // Time-travel + timeline() reads key on (tenant_id, namespace, target_id);
28
+ // changed_at additionally covers the "state as of a timestamp" query.
29
+ db.run(`CREATE INDEX IF NOT EXISTS idx_audit_log_lookup ON audit_log(tenant_id, namespace, target_id, changed_at)`);
30
+ },
31
+ },
32
+ {
33
+ // 05 §A1, the repair half. `0001` above was corrected in place so a fresh
34
+ // database is right from the start — but `CREATE TABLE IF NOT EXISTS` means
35
+ // an EXISTING `audit_log` keeps the old `UNIQUE(namespace, target_id,
36
+ // version_key)`, which is cross-tenant: two tenants whose ids collide
37
+ // (`target_id` is namespace-scoped, not minted per tenant — a plugin's
38
+ // `todo` row "5" is "5" for everybody) contend for the same version
39
+ // sequence, and one tenant's write fails against a row it cannot read.
40
+ //
41
+ // A table-level UNIQUE cannot be altered in SQLite, so this rebuilds. It is
42
+ // ordered AFTER `0001` and guarded on the old constraint actually being
43
+ // present, so on a fresh database it is a no-op rather than a needless copy
44
+ // of the whole audit trail.
45
+ name: '0002_tenant_scoped_version',
46
+ up(db) {
47
+ const schema = db
48
+ .query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'audit_log'")
49
+ .get()?.sql;
50
+ if (!schema || !/UNIQUE\s*\(\s*namespace/i.test(schema))
51
+ return;
52
+ db.run(`
53
+ CREATE TABLE audit_log_0002 (
54
+ audit_id INTEGER PRIMARY KEY AUTOINCREMENT,
55
+ namespace TEXT NOT NULL,
56
+ mutation_key TEXT NOT NULL,
57
+ target_id TEXT NOT NULL,
58
+ version_key INTEGER NOT NULL,
59
+ operation TEXT NOT NULL CHECK (operation IN ('insert', 'update', 'delete')),
60
+ tenant_id TEXT NOT NULL,
61
+ changed_by TEXT,
62
+ changed_at TEXT NOT NULL,
63
+ snapshot_data TEXT,
64
+ UNIQUE(tenant_id, namespace, target_id, version_key)
65
+ )
66
+ `);
67
+ db.run(`
68
+ INSERT INTO audit_log_0002
69
+ (audit_id, namespace, mutation_key, target_id, version_key, operation, tenant_id, changed_by, changed_at, snapshot_data)
70
+ SELECT audit_id, namespace, mutation_key, target_id, version_key, operation, tenant_id, changed_by, changed_at, snapshot_data
71
+ FROM audit_log
72
+ `);
73
+ db.run('DROP TABLE audit_log');
74
+ db.run('ALTER TABLE audit_log_0002 RENAME TO audit_log');
75
+ // The rename does not carry the index — it was dropped with the old table.
76
+ db.run(`CREATE INDEX IF NOT EXISTS idx_audit_log_lookup ON audit_log(tenant_id, namespace, target_id, changed_at)`);
77
+ },
78
+ },
79
+ ];
@@ -0,0 +1,36 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import type { AuditEntryInput, AuditRecord } from 'cwip/audit';
3
+ /**
4
+ * The persistent audit sink: one shared `audit_log` table (see `./migrations`),
5
+ * versioned per `(namespace, targetId)`. Runs its migration on first
6
+ * construction (idempotent — safe to call once per boot per `db`).
7
+ *
8
+ * const sink = createSqliteAuditSink(db);
9
+ * const router = buildServerRouter(runtime, config, { verifyToken, audit: { sink } });
10
+ *
11
+ * Deliberately NOT annotated `: AuditSink` — see `cwip/audit`'s
12
+ * `createMemoryAuditSink` for why (this sink is fully synchronous under the
13
+ * hood; the interface's async-capable signature would erase that at every
14
+ * call site). Structurally assignable to `AuditSink` wherever one is expected.
15
+ */
16
+ export declare function createSqliteAuditSink(db: Database): {
17
+ record(entry: AuditEntryInput): AuditRecord;
18
+ timeline(tenantId: string, namespace: string, targetId: string): AuditRecord[];
19
+ };
20
+ /**
21
+ * Every read below takes `tenantId` FIRST and as a required argument (05 §A1).
22
+ *
23
+ * `audit_log` is ONE shared table across every namespace and every tenant, and
24
+ * its lookup key `(namespace, targetId)` is a business key a plugin chose — not a
25
+ * minted id. So a read that omits the tenant is not merely broad: it returns
26
+ * another tenant's snapshot for the same row number, which is the whole audit
27
+ * trail's contents. Making the parameter optional (defaulting to "all tenants")
28
+ * would put that one keystroke away, so it is required and positioned where a
29
+ * mistaken call fails to typecheck rather than silently widening.
30
+ */
31
+ /** Query 1: the record's state as of a given moment (last version at or before `at`). */
32
+ export declare function auditStateAt(db: Database, tenantId: string, namespace: string, targetId: string, at: string): AuditRecord | null;
33
+ /** Query 2: jump directly to a specific `versionKey`. */
34
+ export declare function auditStateAtVersion(db: Database, tenantId: string, namespace: string, targetId: string, versionKey: number): AuditRecord | null;
35
+ /** Query 3: step one version back/forward from `currentVersion` (for a UI "prev/next" control). */
36
+ export declare function auditStep(db: Database, tenantId: string, namespace: string, targetId: string, currentVersion: number, direction: 'back' | 'forward'): AuditRecord | null;
@@ -0,0 +1,95 @@
1
+ import { runMigrations } from '../migration/runner';
2
+ import { AUDIT_LOG_MIGRATIONS } from './migrations';
3
+ function rowToRecord(row) {
4
+ return {
5
+ namespace: row.namespace,
6
+ mutationKey: row.mutation_key,
7
+ targetId: row.target_id,
8
+ versionKey: row.version_key,
9
+ operation: row.operation,
10
+ tenantId: row.tenant_id,
11
+ changedBy: row.changed_by ?? undefined,
12
+ changedAt: row.changed_at,
13
+ snapshot: row.snapshot_data == null ? null : JSON.parse(row.snapshot_data),
14
+ };
15
+ }
16
+ /**
17
+ * The persistent audit sink: one shared `audit_log` table (see `./migrations`),
18
+ * versioned per `(namespace, targetId)`. Runs its migration on first
19
+ * construction (idempotent — safe to call once per boot per `db`).
20
+ *
21
+ * const sink = createSqliteAuditSink(db);
22
+ * const router = buildServerRouter(runtime, config, { verifyToken, audit: { sink } });
23
+ *
24
+ * Deliberately NOT annotated `: AuditSink` — see `cwip/audit`'s
25
+ * `createMemoryAuditSink` for why (this sink is fully synchronous under the
26
+ * hood; the interface's async-capable signature would erase that at every
27
+ * call site). Structurally assignable to `AuditSink` wherever one is expected.
28
+ */
29
+ export function createSqliteAuditSink(db) {
30
+ runMigrations(db, AUDIT_LOG_MIGRATIONS);
31
+ // Scoped by tenant (05 §A1). `targetId` is a namespace-local business key, not
32
+ // a minted global id — a plugin's `todo` row "5" is "5" for every tenant — so
33
+ // an unscoped MAX() hands tenant B a version number tenant A already used, and
34
+ // the UNIQUE then refuses B's write over a row B may not read.
35
+ const nextVersion = db.prepare('SELECT COALESCE(MAX(version_key), 0) + 1 AS v FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ?');
36
+ const insert = db.prepare(`
37
+ INSERT INTO audit_log
38
+ (namespace, mutation_key, target_id, version_key, operation, tenant_id, changed_by, changed_at, snapshot_data)
39
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
40
+ `);
41
+ const selectTimeline = db.prepare('SELECT * FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ? ORDER BY version_key ASC');
42
+ return {
43
+ record(entry) {
44
+ // No `await` between the read and the write below — bun:sqlite's calls are
45
+ // synchronous, so nothing else can interleave and race the version number.
46
+ const record = db.transaction(() => {
47
+ const { v: versionKey } = nextVersion.get(entry.tenantId, entry.namespace, entry.targetId);
48
+ const changedAt = entry.changedAt ?? new Date().toISOString();
49
+ insert.run(entry.namespace, entry.mutationKey, entry.targetId, versionKey, entry.operation, entry.tenantId, entry.changedBy ?? null, changedAt, entry.snapshot == null ? null : JSON.stringify(entry.snapshot));
50
+ return { ...entry, versionKey, changedAt };
51
+ })();
52
+ return record;
53
+ },
54
+ timeline(tenantId, namespace, targetId) {
55
+ const rows = selectTimeline.all(tenantId, namespace, targetId);
56
+ return rows.map(rowToRecord);
57
+ },
58
+ };
59
+ }
60
+ /**
61
+ * Every read below takes `tenantId` FIRST and as a required argument (05 §A1).
62
+ *
63
+ * `audit_log` is ONE shared table across every namespace and every tenant, and
64
+ * its lookup key `(namespace, targetId)` is a business key a plugin chose — not a
65
+ * minted id. So a read that omits the tenant is not merely broad: it returns
66
+ * another tenant's snapshot for the same row number, which is the whole audit
67
+ * trail's contents. Making the parameter optional (defaulting to "all tenants")
68
+ * would put that one keystroke away, so it is required and positioned where a
69
+ * mistaken call fails to typecheck rather than silently widening.
70
+ */
71
+ /** Query 1: the record's state as of a given moment (last version at or before `at`). */
72
+ export function auditStateAt(db, tenantId, namespace, targetId, at) {
73
+ const row = db
74
+ .prepare('SELECT * FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ? AND changed_at <= ? ORDER BY version_key DESC LIMIT 1')
75
+ .get(tenantId, namespace, targetId, at);
76
+ return row ? rowToRecord(row) : null;
77
+ }
78
+ /** Query 2: jump directly to a specific `versionKey`. */
79
+ export function auditStateAtVersion(db, tenantId, namespace, targetId, versionKey) {
80
+ const row = db
81
+ .prepare('SELECT * FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ? AND version_key = ?')
82
+ .get(tenantId, namespace, targetId, versionKey);
83
+ return row ? rowToRecord(row) : null;
84
+ }
85
+ /** Query 3: step one version back/forward from `currentVersion` (for a UI "prev/next" control). */
86
+ export function auditStep(db, tenantId, namespace, targetId, currentVersion, direction) {
87
+ const row = direction === 'back'
88
+ ? db
89
+ .prepare('SELECT * FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ? AND version_key < ? ORDER BY version_key DESC LIMIT 1')
90
+ .get(tenantId, namespace, targetId, currentVersion)
91
+ : db
92
+ .prepare('SELECT * FROM audit_log WHERE tenant_id = ? AND namespace = ? AND target_id = ? AND version_key > ? ORDER BY version_key ASC LIMIT 1')
93
+ .get(tenantId, namespace, targetId, currentVersion);
94
+ return row ? rowToRecord(row) : null;
95
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,180 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { beforeEach, describe, expect, it } from 'bun:test';
3
+ import { auditStateAt, auditStateAtVersion, auditStep, createSqliteAuditSink } from './sqliteSink';
4
+ let db;
5
+ beforeEach(() => {
6
+ db = new Database(':memory:');
7
+ });
8
+ describe('createSqliteAuditSink', () => {
9
+ it('assigns sequential version keys per (namespace, targetId) and persists snapshots', async () => {
10
+ const sink = createSqliteAuditSink(db);
11
+ const v1 = await sink.record({
12
+ namespace: 'todo',
13
+ mutationKey: 'add',
14
+ targetId: '5',
15
+ operation: 'insert',
16
+ snapshot: { id: '5', title: 'a' },
17
+ tenantId: 't1',
18
+ changedBy: 'u1',
19
+ });
20
+ const v2 = await sink.record({
21
+ namespace: 'todo',
22
+ mutationKey: 'update',
23
+ targetId: '5',
24
+ operation: 'update',
25
+ snapshot: { id: '5', title: 'b' },
26
+ tenantId: 't1',
27
+ });
28
+ expect(v1.versionKey).toBe(1);
29
+ expect(v2.versionKey).toBe(2);
30
+ expect(v1.snapshot).toEqual({ id: '5', title: 'a' });
31
+ });
32
+ it('stores a null snapshot for delete tombstones', async () => {
33
+ const sink = createSqliteAuditSink(db);
34
+ const deleted = await sink.record({
35
+ namespace: 'todo',
36
+ mutationKey: 'remove',
37
+ targetId: '5',
38
+ operation: 'delete',
39
+ snapshot: null,
40
+ tenantId: 't1',
41
+ });
42
+ expect(deleted.snapshot).toBeNull();
43
+ });
44
+ it('is idempotent to construct twice against the same db (migration re-run is a no-op)', () => {
45
+ createSqliteAuditSink(db);
46
+ expect(() => createSqliteAuditSink(db)).not.toThrow();
47
+ });
48
+ it('timeline() returns full history oldest-first', async () => {
49
+ const sink = createSqliteAuditSink(db);
50
+ await sink.record({
51
+ namespace: 'todo',
52
+ mutationKey: 'add',
53
+ targetId: '5',
54
+ operation: 'insert',
55
+ snapshot: { title: 'a' },
56
+ tenantId: 't1',
57
+ });
58
+ await sink.record({
59
+ namespace: 'todo',
60
+ mutationKey: 'remove',
61
+ targetId: '5',
62
+ operation: 'delete',
63
+ snapshot: null,
64
+ tenantId: 't1',
65
+ });
66
+ const timeline = await sink.timeline('t1', 'todo', '5');
67
+ expect(timeline.map((r) => r.operation)).toEqual(['insert', 'delete']);
68
+ });
69
+ // 05 §A1. `targetId` is a namespace-local business key, not a minted id, so
70
+ // two tenants routinely mutate "5". Before the tenant joined the UNIQUE and
71
+ // the MAX() that feeds it, tenant B's first write took version 2 — or was
72
+ // refused outright by tenant A's row — and B's timeline read A's history.
73
+ it('versions and reads per TENANT, not just per (namespace, targetId)', async () => {
74
+ const sink = createSqliteAuditSink(db);
75
+ const entry = (tenantId, title) => ({
76
+ namespace: 'todo',
77
+ mutationKey: 'add',
78
+ targetId: '5',
79
+ operation: 'insert',
80
+ snapshot: { title },
81
+ tenantId,
82
+ });
83
+ const first = await sink.record(entry('t1', 'a'));
84
+ const second = await sink.record(entry('t2', 'b'));
85
+ expect(first.versionKey).toBe(1);
86
+ expect(second.versionKey).toBe(1);
87
+ expect((await sink.timeline('t2', 'todo', '5')).map((r) => r.snapshot)).toEqual([{ title: 'b' }]);
88
+ expect(auditStateAtVersion(db, 't1', 'todo', '5', 1)?.snapshot).toEqual({ title: 'a' });
89
+ });
90
+ // The repair half: a database created before this landing carries
91
+ // `UNIQUE(namespace, target_id, version_key)` and `CREATE TABLE IF NOT EXISTS`
92
+ // would never correct it, so `0002` rebuilds — preserving the rows.
93
+ it('rebuilds a pre-existing audit_log that carries the cross-tenant UNIQUE', () => {
94
+ db.run(`
95
+ CREATE TABLE audit_log (
96
+ audit_id INTEGER PRIMARY KEY AUTOINCREMENT,
97
+ namespace TEXT NOT NULL,
98
+ mutation_key TEXT NOT NULL,
99
+ target_id TEXT NOT NULL,
100
+ version_key INTEGER NOT NULL,
101
+ operation TEXT NOT NULL CHECK (operation IN ('insert', 'update', 'delete')),
102
+ tenant_id TEXT NOT NULL,
103
+ changed_by TEXT,
104
+ changed_at TEXT NOT NULL,
105
+ snapshot_data TEXT,
106
+ UNIQUE(namespace, target_id, version_key)
107
+ )
108
+ `);
109
+ db.run(`INSERT INTO audit_log (namespace, mutation_key, target_id, version_key, operation, tenant_id, changed_at, snapshot_data)
110
+ VALUES ('todo', 'add', '5', 1, 'insert', 't1', '2026-01-01T00:00:00.000Z', '{"title":"kept"}')`);
111
+ const sink = createSqliteAuditSink(db);
112
+ const schema = db.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'audit_log'").get().sql;
113
+ expect(schema).toContain('UNIQUE(tenant_id, namespace, target_id, version_key)');
114
+ // The history survived the rebuild …
115
+ expect(auditStateAtVersion(db, 't1', 'todo', '5', 1)?.snapshot).toEqual({ title: 'kept' });
116
+ // … and the constraint the rebuild exists for now holds.
117
+ const other = sink.record({
118
+ namespace: 'todo',
119
+ mutationKey: 'add',
120
+ targetId: '5',
121
+ operation: 'insert',
122
+ snapshot: { title: 'theirs' },
123
+ tenantId: 't2',
124
+ });
125
+ expect(other.versionKey).toBe(1);
126
+ });
127
+ });
128
+ describe('time-travel queries', () => {
129
+ const seed = async () => {
130
+ const sink = createSqliteAuditSink(db);
131
+ await sink.record({
132
+ namespace: 'todo',
133
+ mutationKey: 'add',
134
+ targetId: '5',
135
+ operation: 'insert',
136
+ snapshot: { title: 'v1' },
137
+ tenantId: 't1',
138
+ changedAt: '2026-01-01T00:00:00.000Z',
139
+ });
140
+ await sink.record({
141
+ namespace: 'todo',
142
+ mutationKey: 'update',
143
+ targetId: '5',
144
+ operation: 'update',
145
+ snapshot: { title: 'v2' },
146
+ tenantId: 't1',
147
+ changedAt: '2026-01-02T00:00:00.000Z',
148
+ });
149
+ await sink.record({
150
+ namespace: 'todo',
151
+ mutationKey: 'update',
152
+ targetId: '5',
153
+ operation: 'update',
154
+ snapshot: { title: 'v3' },
155
+ tenantId: 't1',
156
+ changedAt: '2026-01-03T00:00:00.000Z',
157
+ });
158
+ };
159
+ it('auditStateAt returns the last version at or before the given time', async () => {
160
+ await seed();
161
+ const state = auditStateAt(db, 't1', 'todo', '5', '2026-01-02T12:00:00.000Z');
162
+ expect(state?.snapshot).toEqual({ title: 'v2' });
163
+ });
164
+ it('auditStateAt returns null before any history exists', async () => {
165
+ await seed();
166
+ expect(auditStateAt(db, 't1', 'todo', '5', '2025-12-31T00:00:00.000Z')).toBeNull();
167
+ });
168
+ it('auditStateAtVersion jumps directly to a version', async () => {
169
+ await seed();
170
+ expect(auditStateAtVersion(db, 't1', 'todo', '5', 1)?.snapshot).toEqual({ title: 'v1' });
171
+ expect(auditStateAtVersion(db, 't1', 'todo', '5', 99)).toBeNull();
172
+ });
173
+ it('auditStep walks back and forward one version', async () => {
174
+ await seed();
175
+ expect(auditStep(db, 't1', 'todo', '5', 2, 'back')?.versionKey).toBe(1);
176
+ expect(auditStep(db, 't1', 'todo', '5', 2, 'forward')?.versionKey).toBe(3);
177
+ expect(auditStep(db, 't1', 'todo', '5', 1, 'back')).toBeNull();
178
+ expect(auditStep(db, 't1', 'todo', '5', 3, 'forward')).toBeNull();
179
+ });
180
+ });
@@ -0,0 +1,22 @@
1
+ import type { Context } from 'hono';
2
+ /**
3
+ * Cookie helpers on `hono/cookie` (replacing `cookie-parser` + Express
4
+ * `res.cookie`). Two cookies, two deliberately-different `sameSite` postures:
5
+ *
6
+ * - `access_token` — httpOnly, **`sameSite: Lax`** so it rides top-level
7
+ * navigations (a returning user lands authenticated). The JWT is the auth
8
+ * credential; JS must never read it.
9
+ * - `csrf_token` — JS-readable (the SPA echoes it in a header), **`sameSite:
10
+ * Strict`** so it is NOT attached to cross-site requests. The two MUST stay
11
+ * separate cookies (see {@link ./csrf}).
12
+ */
13
+ export declare const AUTH_COOKIE_NAME = "access_token";
14
+ /** Read the httpOnly auth cookie (the access JWT), or undefined. */
15
+ export declare function readAuthCookie(c: Context): string | undefined;
16
+ /**
17
+ * Write the auth cookie. `maxAge` is seconds (cookie spec) — pass the access
18
+ * token's lifetime. httpOnly + `sameSite: Lax`, secure in production.
19
+ */
20
+ export declare function writeAuthCookie(c: Context, token: string, maxAge: number): void;
21
+ /** Clear the auth cookie (logout). */
22
+ export declare function clearAuthCookie(c: Context): void;
@@ -0,0 +1,35 @@
1
+ import { deleteCookie, getCookie, setCookie } from 'hono/cookie';
2
+ /**
3
+ * Cookie helpers on `hono/cookie` (replacing `cookie-parser` + Express
4
+ * `res.cookie`). Two cookies, two deliberately-different `sameSite` postures:
5
+ *
6
+ * - `access_token` — httpOnly, **`sameSite: Lax`** so it rides top-level
7
+ * navigations (a returning user lands authenticated). The JWT is the auth
8
+ * credential; JS must never read it.
9
+ * - `csrf_token` — JS-readable (the SPA echoes it in a header), **`sameSite:
10
+ * Strict`** so it is NOT attached to cross-site requests. The two MUST stay
11
+ * separate cookies (see {@link ./csrf}).
12
+ */
13
+ export const AUTH_COOKIE_NAME = 'access_token';
14
+ const isProd = () => process.env.NODE_ENV === 'production';
15
+ /** Read the httpOnly auth cookie (the access JWT), or undefined. */
16
+ export function readAuthCookie(c) {
17
+ return getCookie(c, AUTH_COOKIE_NAME);
18
+ }
19
+ /**
20
+ * Write the auth cookie. `maxAge` is seconds (cookie spec) — pass the access
21
+ * token's lifetime. httpOnly + `sameSite: Lax`, secure in production.
22
+ */
23
+ export function writeAuthCookie(c, token, maxAge) {
24
+ setCookie(c, AUTH_COOKIE_NAME, token, {
25
+ httpOnly: true,
26
+ secure: isProd(),
27
+ sameSite: 'Lax',
28
+ maxAge,
29
+ path: '/',
30
+ });
31
+ }
32
+ /** Clear the auth cookie (logout). */
33
+ export function clearAuthCookie(c) {
34
+ deleteCookie(c, AUTH_COOKIE_NAME, { path: '/' });
35
+ }
@@ -0,0 +1,42 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ /**
3
+ * Double-submit CSRF guard for the cookie-auth + ctgr GET-tunnel model.
4
+ *
5
+ * Because mutations tunnel through a GET (the ctgr twin) and the auth cookie is
6
+ * `sameSite: Lax`, a cross-site top-level navigation could otherwise trigger a
7
+ * state change. We defend with a JS-readable, `sameSite: Strict` `csrf_token`
8
+ * cookie that the SPA echoes back in the `x-csrf-token` header. A cross-origin page
9
+ * can neither read the victim's cookie nor (Strict) cause it to be sent on a
10
+ * cross-site request, so it cannot forge the header.
11
+ *
12
+ * Behavior:
13
+ * - Safe verbs (GET/HEAD) OUTSIDE the protected prefix: mint the `csrf_token`
14
+ * cookie if absent (so a returning user has it on first paint), then continue.
15
+ * Genuine reads are never CSRF-checked.
16
+ * - ANY request whose path starts with the protected prefix (default `/ctgr`),
17
+ * regardless of HTTP method: require `header === cookie`, else 403. Every ctgr
18
+ * request is a tunneled mutation — and the twin rides a *GET* — so the check must
19
+ * fire even on GET here, or the exact attack CSRF defends against (a cross-site
20
+ * navigation/`<img>` to a `/ctgr*` mutation) slips through. Enforcing on the
21
+ * prefix (not the verb) keeps the guarantee independent of where task-25's
22
+ * `unGETify` sits in the chain. (Invariant #2: ctgr protection may never weaken.)
23
+ * - Mutating verbs OUTSIDE the prefix are NOT checked here (in production all
24
+ * mutations come through ctgr; direct verbs are internal/test traffic).
25
+ *
26
+ * MOUNT GLOBALLY — `app.use('*', createCsrfMiddleware())`. It matches the prefix with
27
+ * a plain `path.startsWith`, so it is immune to Hono's `/ctgr*`-doesn't-match wildcard
28
+ * gotcha; do NOT mount it on `CTGR_ROUTE_PATTERN` (that pattern is for the `unGETify`
29
+ * decode mount) — a prefix-only mount would never run on normal reads and so would
30
+ * never mint the `csrf_token` cookie.
31
+ */
32
+ export interface CsrfOptions {
33
+ /** Path prefix whose requests are CSRF-checked. Default `/ctgr`. */
34
+ protectedPrefix?: string;
35
+ /** Cookie name. Default `csrf_token`. */
36
+ cookieName?: string;
37
+ /** Request header the SPA echoes the token in. Default `x-csrf-token`. */
38
+ headerName?: string;
39
+ }
40
+ export declare const CSRF_COOKIE_NAME = "csrf_token";
41
+ export declare const CSRF_HEADER_NAME = "x-csrf-token";
42
+ export declare function createCsrfMiddleware(opts?: CsrfOptions): MiddlewareHandler;
@@ -0,0 +1,36 @@
1
+ import { getCookie, setCookie } from 'hono/cookie';
2
+ import { ApiError, toErrorEnvelope } from '../errors';
3
+ export const CSRF_COOKIE_NAME = 'csrf_token';
4
+ export const CSRF_HEADER_NAME = 'x-csrf-token';
5
+ const isProd = () => process.env.NODE_ENV === 'production';
6
+ export function createCsrfMiddleware(opts = {}) {
7
+ const prefix = opts.protectedPrefix ?? '/ctgr';
8
+ const cookieName = opts.cookieName ?? CSRF_COOKIE_NAME;
9
+ const headerName = opts.headerName ?? CSRF_HEADER_NAME;
10
+ return async (c, next) => {
11
+ const method = c.req.method;
12
+ const isProtected = c.req.path.startsWith(prefix);
13
+ // Genuine reads (outside the ctgr tunnel): mint the cookie, never enforce.
14
+ if (!isProtected && (method === 'GET' || method === 'HEAD')) {
15
+ if (!getCookie(c, cookieName)) {
16
+ setCookie(c, cookieName, crypto.randomUUID(), {
17
+ httpOnly: false, // the SPA must read it to echo it back
18
+ secure: isProd(),
19
+ sameSite: 'Strict',
20
+ path: '/',
21
+ });
22
+ }
23
+ return next();
24
+ }
25
+ // Every ctgr request is a tunneled mutation (the twin is a GET) — enforce here
26
+ // regardless of verb. Non-ctgr mutating verbs fall through unchecked.
27
+ if (isProtected) {
28
+ const header = c.req.header(headerName);
29
+ const cookie = getCookie(c, cookieName);
30
+ if (!header || header !== cookie) {
31
+ return c.json(toErrorEnvelope(new ApiError(403, 'Invalid CSRF token')), 403);
32
+ }
33
+ }
34
+ return next();
35
+ };
36
+ }
@@ -0,0 +1,10 @@
1
+ import type { FileTokenSigner } from '../storage/binaryServerStore';
2
+ export type Rs256FileTokenSignerOptions = {
3
+ /** PKCS8 PEM private key. `\n` escape sequences are accepted (env-var friendly). */
4
+ privateKeyPem: string;
5
+ /** The `iss` claim — must match the issuer the tenant was registered with. */
6
+ issuer: string;
7
+ /** Token lifetime in seconds (default 6h — long enough for a paused, resumed video). */
8
+ ttlSeconds?: number;
9
+ };
10
+ export declare function createRs256FileTokenSigner(opts: Rs256FileTokenSignerOptions): FileTokenSigner;
@@ -0,0 +1,22 @@
1
+ import { importPKCS8, SignJWT } from 'jose';
2
+ export function createRs256FileTokenSigner(opts) {
3
+ const ttl = opts.ttlSeconds ?? 6 * 60 * 60;
4
+ const pem = opts.privateKeyPem.includes('-----')
5
+ ? opts.privateKeyPem.replace(/\\n/g, '\n')
6
+ : Buffer.from(opts.privateKeyPem, 'base64').toString('utf8');
7
+ // Lazy: a bad key must surface as a sign-time error, not an unhandled
8
+ // rejection parked on a module-scope promise from construction time.
9
+ let keyPromise = null;
10
+ return async (claims) => {
11
+ keyPromise ??= importPKCS8(pem, 'RS256');
12
+ const key = await keyPromise;
13
+ // Drop undefined values — jose serializes them as null otherwise.
14
+ const payload = Object.fromEntries(Object.entries(claims).filter(([, v]) => v !== undefined));
15
+ return new SignJWT(payload)
16
+ .setProtectedHeader({ alg: 'RS256' })
17
+ .setIssuer(opts.issuer)
18
+ .setIssuedAt()
19
+ .setExpirationTime(`${ttl}s`)
20
+ .sign(key);
21
+ };
22
+ }
@@ -0,0 +1,20 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ import type { AuthEnv } from './types';
3
+ /**
4
+ * `getOnly` enforcement — the server-side half of the `/f` GET-only session
5
+ * guarantee. A getOnly session (the obfuscated `/f` login) may read freely and may
6
+ * mutate ONLY through the ctgr GET-twins (which are GETs at the transport level);
7
+ * any raw non-GET/HEAD verb from such a session is rejected with 403.
8
+ *
9
+ * Mount GLOBALLY (`app.use('*', getOnlyEnforcement())`) AFTER `createAuthMiddleware`
10
+ * — it reads the `user` the auth middleware sets and gates purely on the HTTP verb,
11
+ * so it needs no ctgr path pattern (it must see EVERY mutating request, not only
12
+ * `/ctgr*`). A non-getOnly session — or an unauthenticated request that never reached
13
+ * here — passes through untouched.
14
+ */
15
+ /** Pure predicate: does this principal+method combination violate the GET-only
16
+ * rule? Exposed for direct unit testing and reuse outside the middleware. */
17
+ export declare function isGetOnlyViolation(user: {
18
+ getOnly?: boolean;
19
+ }, method: string): boolean;
20
+ export declare function getOnlyEnforcement(): MiddlewareHandler<AuthEnv>;
@@ -0,0 +1,27 @@
1
+ import { ApiError, toErrorEnvelope } from '../errors';
2
+ /**
3
+ * `getOnly` enforcement — the server-side half of the `/f` GET-only session
4
+ * guarantee. A getOnly session (the obfuscated `/f` login) may read freely and may
5
+ * mutate ONLY through the ctgr GET-twins (which are GETs at the transport level);
6
+ * any raw non-GET/HEAD verb from such a session is rejected with 403.
7
+ *
8
+ * Mount GLOBALLY (`app.use('*', getOnlyEnforcement())`) AFTER `createAuthMiddleware`
9
+ * — it reads the `user` the auth middleware sets and gates purely on the HTTP verb,
10
+ * so it needs no ctgr path pattern (it must see EVERY mutating request, not only
11
+ * `/ctgr*`). A non-getOnly session — or an unauthenticated request that never reached
12
+ * here — passes through untouched.
13
+ */
14
+ /** Pure predicate: does this principal+method combination violate the GET-only
15
+ * rule? Exposed for direct unit testing and reuse outside the middleware. */
16
+ export function isGetOnlyViolation(user, method) {
17
+ return user.getOnly === true && method !== 'GET' && method !== 'HEAD';
18
+ }
19
+ export function getOnlyEnforcement() {
20
+ return async (c, next) => {
21
+ const user = c.get('user');
22
+ if (user && isGetOnlyViolation(user, c.req.method)) {
23
+ return c.json(toErrorEnvelope(new ApiError(403, 'GET-only session')), 403);
24
+ }
25
+ return next();
26
+ };
27
+ }
@@ -0,0 +1,12 @@
1
+ export { AUTH_COOKIE_NAME, clearAuthCookie, readAuthCookie, writeAuthCookie, } from './cookie';
2
+ export { CSRF_COOKIE_NAME, CSRF_HEADER_NAME, type CsrfOptions, createCsrfMiddleware } from './csrf';
3
+ export { createRs256FileTokenSigner, type Rs256FileTokenSignerOptions, } from './fileTokenSigner';
4
+ export { getOnlyEnforcement, isGetOnlyViolation } from './getOnly';
5
+ export { signToken, verifyPurposeToken, verifyToken } from './jwt';
6
+ export { clientKeyOf, clientKeyOfContext, createLoginThrottle, type LoginThrottle, type LoginThrottleOptions, type ThrottleVerdict, } from './loginThrottle';
7
+ export { createAuthMiddleware } from './middleware';
8
+ export { hashPassword, needsRehash, verifyPassword } from './password';
9
+ export { createSessionStore, type SessionStoreOptions, } from './sessionStore';
10
+ export { DEFAULT_TOTP_ISSUER, generateRecoveryCodes, generateTotpSecret, getTotpUri, verifyRecoveryCode, verifyTotpCode, } from './totp';
11
+ export type { AppJwtPayload, AuthEnv, AuthUser, AuthVariables, CreateSessionInput, Session, SessionStore, TokenPurpose, } from './types';
12
+ export { decryptVaultItem, deriveVaultKey, encryptVaultItem } from './vault';
@@ -0,0 +1,15 @@
1
+ // cursedbelt server auth toolkit (task 26) — jose JWT, cookies, CSRF, the getOnly
2
+ // gate, a Kysely-backed session store, login throttle, argon2id passwords, TOTP, and
3
+ // Web-Crypto vault item crypto. The *mechanism* lives here; the *model* (roles,
4
+ // sharing, the `/f`-vs-`/login` policy, session semantics) stays in the apps.
5
+ export { AUTH_COOKIE_NAME, clearAuthCookie, readAuthCookie, writeAuthCookie, } from './cookie';
6
+ export { CSRF_COOKIE_NAME, CSRF_HEADER_NAME, createCsrfMiddleware } from './csrf';
7
+ export { createRs256FileTokenSigner, } from './fileTokenSigner';
8
+ export { getOnlyEnforcement, isGetOnlyViolation } from './getOnly';
9
+ export { signToken, verifyPurposeToken, verifyToken } from './jwt';
10
+ export { clientKeyOf, clientKeyOfContext, createLoginThrottle, } from './loginThrottle';
11
+ export { createAuthMiddleware } from './middleware';
12
+ export { hashPassword, needsRehash, verifyPassword } from './password';
13
+ export { createSessionStore, } from './sessionStore';
14
+ export { DEFAULT_TOTP_ISSUER, generateRecoveryCodes, generateTotpSecret, getTotpUri, verifyRecoveryCode, verifyTotpCode, } from './totp';
15
+ export { decryptVaultItem, deriveVaultKey, encryptVaultItem } from './vault';