@gettersethya/mira 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (371) hide show
  1. package/README.md +174 -0
  2. package/dist/src/app/app.d.ts +45 -26
  3. package/dist/src/app/app.d.ts.map +1 -1
  4. package/dist/src/app/app.js +138 -41
  5. package/dist/src/app/app.js.map +1 -1
  6. package/dist/src/app/builder.d.ts +56 -15
  7. package/dist/src/app/builder.d.ts.map +1 -1
  8. package/dist/src/app/builder.js +56 -4
  9. package/dist/src/app/builder.js.map +1 -1
  10. package/dist/src/app/define-rule.d.ts +70 -0
  11. package/dist/src/app/define-rule.d.ts.map +1 -0
  12. package/dist/src/app/define-rule.js +42 -0
  13. package/dist/src/app/define-rule.js.map +1 -0
  14. package/dist/src/app/index.d.ts +8 -3
  15. package/dist/src/app/index.d.ts.map +1 -1
  16. package/dist/src/app/index.js +3 -0
  17. package/dist/src/app/index.js.map +1 -1
  18. package/dist/src/app/plugin.d.ts +83 -0
  19. package/dist/src/app/plugin.d.ts.map +1 -0
  20. package/dist/src/app/plugin.js +20 -0
  21. package/dist/src/app/plugin.js.map +1 -0
  22. package/dist/src/app/types.d.ts +4 -4
  23. package/dist/src/app/types.d.ts.map +1 -1
  24. package/dist/src/cache/cached-collection.d.ts +7 -5
  25. package/dist/src/cache/cached-collection.d.ts.map +1 -1
  26. package/dist/src/cache/cached-collection.js +8 -5
  27. package/dist/src/cache/cached-collection.js.map +1 -1
  28. package/dist/src/cache/collection-cache.d.ts +1 -1
  29. package/dist/src/cache/collection-cache.d.ts.map +1 -1
  30. package/dist/src/cache/collection-cache.js +1 -1
  31. package/dist/src/cache/collection-cache.js.map +1 -1
  32. package/dist/src/cache/ctx-key.d.ts +15 -0
  33. package/dist/src/cache/ctx-key.d.ts.map +1 -0
  34. package/dist/src/cache/ctx-key.js +37 -0
  35. package/dist/src/cache/ctx-key.js.map +1 -0
  36. package/dist/src/cache/index.d.ts +2 -1
  37. package/dist/src/cache/index.d.ts.map +1 -1
  38. package/dist/src/cache/index.js +2 -1
  39. package/dist/src/cache/index.js.map +1 -1
  40. package/dist/src/collection-service/collection-service.d.ts +7 -5
  41. package/dist/src/collection-service/collection-service.d.ts.map +1 -1
  42. package/dist/src/collection-service/collection-service.js +201 -51
  43. package/dist/src/collection-service/collection-service.js.map +1 -1
  44. package/dist/src/collection-service/context.d.ts +2 -0
  45. package/dist/src/collection-service/context.d.ts.map +1 -1
  46. package/dist/src/collection-service/decode.d.ts +4 -2
  47. package/dist/src/collection-service/decode.d.ts.map +1 -1
  48. package/dist/src/collection-service/decode.js +32 -16
  49. package/dist/src/collection-service/decode.js.map +1 -1
  50. package/dist/src/collection-service/errors.d.ts +1 -1
  51. package/dist/src/collection-service/errors.d.ts.map +1 -1
  52. package/dist/src/collection-service/errors.js +1 -1
  53. package/dist/src/collection-service/errors.js.map +1 -1
  54. package/dist/src/collection-service/index.d.ts +1 -1
  55. package/dist/src/collection-service/index.d.ts.map +1 -1
  56. package/dist/src/collection-service/index.js.map +1 -1
  57. package/dist/src/collection-service/input-schema.d.ts +5 -4
  58. package/dist/src/collection-service/input-schema.d.ts.map +1 -1
  59. package/dist/src/collection-service/input-schema.js +31 -18
  60. package/dist/src/collection-service/input-schema.js.map +1 -1
  61. package/dist/src/collection-service/where.d.ts +14 -2
  62. package/dist/src/collection-service/where.d.ts.map +1 -1
  63. package/dist/src/collection-service/where.js +35 -1
  64. package/dist/src/collection-service/where.js.map +1 -1
  65. package/dist/src/config/config.d.ts +4 -4
  66. package/dist/src/config/config.d.ts.map +1 -1
  67. package/dist/src/config/config.js +34 -5
  68. package/dist/src/config/config.js.map +1 -1
  69. package/dist/src/config/types.d.ts +9 -0
  70. package/dist/src/config/types.d.ts.map +1 -1
  71. package/dist/src/cron/cron-service.d.ts +14 -0
  72. package/dist/src/cron/cron-service.d.ts.map +1 -0
  73. package/dist/src/cron/cron-service.js +135 -0
  74. package/dist/src/cron/cron-service.js.map +1 -0
  75. package/dist/src/cron/index.d.ts +4 -0
  76. package/dist/src/cron/index.d.ts.map +1 -0
  77. package/dist/src/cron/index.js +3 -0
  78. package/dist/src/cron/index.js.map +1 -0
  79. package/dist/src/cron/persistence.d.ts +22 -0
  80. package/dist/src/cron/persistence.d.ts.map +1 -0
  81. package/dist/src/cron/persistence.js +48 -0
  82. package/dist/src/cron/persistence.js.map +1 -0
  83. package/dist/src/cron/types.d.ts +51 -0
  84. package/dist/src/cron/types.d.ts.map +1 -0
  85. package/dist/src/cron/types.js +4 -0
  86. package/dist/src/cron/types.js.map +1 -0
  87. package/dist/src/crypto/crypto.d.ts +3 -2
  88. package/dist/src/crypto/crypto.d.ts.map +1 -1
  89. package/dist/src/crypto/crypto.js +1 -1
  90. package/dist/src/crypto/crypto.js.map +1 -1
  91. package/dist/src/crypto/node.d.ts.map +1 -1
  92. package/dist/src/crypto/node.js.map +1 -1
  93. package/dist/src/databases/sqlite.d.ts.map +1 -1
  94. package/dist/src/databases/sqlite.js +2 -2
  95. package/dist/src/databases/sqlite.js.map +1 -1
  96. package/dist/src/dialect/dialect-sqlite.d.ts +9 -0
  97. package/dist/src/dialect/dialect-sqlite.d.ts.map +1 -0
  98. package/dist/src/dialect/dialect-sqlite.js +109 -0
  99. package/dist/src/dialect/dialect-sqlite.js.map +1 -0
  100. package/dist/src/dialect/dialect.d.ts +26 -0
  101. package/dist/src/dialect/dialect.d.ts.map +1 -0
  102. package/dist/src/dialect/dialect.js +5 -0
  103. package/dist/src/dialect/dialect.js.map +1 -0
  104. package/dist/src/hooks/hook-collection.d.ts +5 -0
  105. package/dist/src/hooks/hook-collection.d.ts.map +1 -0
  106. package/dist/src/hooks/hook-collection.js +77 -0
  107. package/dist/src/hooks/hook-collection.js.map +1 -0
  108. package/dist/src/hooks/hook-service.d.ts +38 -0
  109. package/dist/src/hooks/hook-service.d.ts.map +1 -0
  110. package/dist/src/hooks/hook-service.js +150 -0
  111. package/dist/src/hooks/hook-service.js.map +1 -0
  112. package/dist/src/hooks/index.d.ts +4 -0
  113. package/dist/src/hooks/index.d.ts.map +1 -0
  114. package/dist/src/hooks/index.js +3 -0
  115. package/dist/src/hooks/index.js.map +1 -0
  116. package/dist/src/hooks/types.d.ts +74 -0
  117. package/dist/src/hooks/types.d.ts.map +1 -0
  118. package/dist/src/hooks/types.js +2 -0
  119. package/dist/src/hooks/types.js.map +1 -0
  120. package/dist/src/http/auth-node.d.ts.map +1 -1
  121. package/dist/src/http/auth-node.js +1 -1
  122. package/dist/src/http/auth-node.js.map +1 -1
  123. package/dist/src/http/auth.d.ts +3 -1
  124. package/dist/src/http/auth.d.ts.map +1 -1
  125. package/dist/src/http/auth.js +12 -2
  126. package/dist/src/http/auth.js.map +1 -1
  127. package/dist/src/http/cors.d.ts +94 -0
  128. package/dist/src/http/cors.d.ts.map +1 -0
  129. package/dist/src/http/cors.js +57 -0
  130. package/dist/src/http/cors.js.map +1 -0
  131. package/dist/src/http/errors.d.ts +1 -1
  132. package/dist/src/http/errors.d.ts.map +1 -1
  133. package/dist/src/http/errors.js +7 -7
  134. package/dist/src/http/errors.js.map +1 -1
  135. package/dist/src/http/file-serve.d.ts +4 -4
  136. package/dist/src/http/file-serve.d.ts.map +1 -1
  137. package/dist/src/http/file-serve.js +39 -34
  138. package/dist/src/http/file-serve.js.map +1 -1
  139. package/dist/src/http/file-token.d.ts +4 -3
  140. package/dist/src/http/file-token.d.ts.map +1 -1
  141. package/dist/src/http/file-token.js +19 -17
  142. package/dist/src/http/file-token.js.map +1 -1
  143. package/dist/src/http/files.d.ts +3 -3
  144. package/dist/src/http/files.d.ts.map +1 -1
  145. package/dist/src/http/files.js +5 -5
  146. package/dist/src/http/files.js.map +1 -1
  147. package/dist/src/http/index.d.ts +8 -5
  148. package/dist/src/http/index.d.ts.map +1 -1
  149. package/dist/src/http/index.js +5 -3
  150. package/dist/src/http/index.js.map +1 -1
  151. package/dist/src/http/ip-middleware.d.ts +3 -2
  152. package/dist/src/http/ip-middleware.d.ts.map +1 -1
  153. package/dist/src/http/ip-middleware.js +7 -4
  154. package/dist/src/http/ip-middleware.js.map +1 -1
  155. package/dist/src/http/params.d.ts +3 -3
  156. package/dist/src/http/params.d.ts.map +1 -1
  157. package/dist/src/http/params.js +2 -2
  158. package/dist/src/http/params.js.map +1 -1
  159. package/dist/src/http/port-retry.d.ts +18 -0
  160. package/dist/src/http/port-retry.d.ts.map +1 -0
  161. package/dist/src/http/port-retry.js +43 -0
  162. package/dist/src/http/port-retry.js.map +1 -0
  163. package/dist/src/http/router.d.ts +10 -7
  164. package/dist/src/http/router.d.ts.map +1 -1
  165. package/dist/src/http/router.js +184 -63
  166. package/dist/src/http/router.js.map +1 -1
  167. package/dist/src/http/schema.d.ts +5 -0
  168. package/dist/src/http/schema.d.ts.map +1 -0
  169. package/dist/src/http/schema.js +18 -0
  170. package/dist/src/http/schema.js.map +1 -0
  171. package/dist/src/http/server-factory-node.d.ts.map +1 -1
  172. package/dist/src/http/server-factory-node.js +1 -1
  173. package/dist/src/http/server-factory-node.js.map +1 -1
  174. package/dist/src/http/server-factory.d.ts +3 -3
  175. package/dist/src/http/server-factory.d.ts.map +1 -1
  176. package/dist/src/http/server-factory.js +1 -1
  177. package/dist/src/http/server-factory.js.map +1 -1
  178. package/dist/src/http/telemetry-routes.d.ts +5 -0
  179. package/dist/src/http/telemetry-routes.d.ts.map +1 -0
  180. package/dist/src/http/telemetry-routes.js +220 -0
  181. package/dist/src/http/telemetry-routes.js.map +1 -0
  182. package/dist/src/index.d.ts +18 -1
  183. package/dist/src/index.d.ts.map +1 -1
  184. package/dist/src/index.js +14 -1
  185. package/dist/src/index.js.map +1 -1
  186. package/dist/src/migrator/dialect-sqlite.d.ts.map +1 -1
  187. package/dist/src/migrator/dialect-sqlite.js +7 -1
  188. package/dist/src/migrator/dialect-sqlite.js.map +1 -1
  189. package/dist/src/migrator/index.d.ts +4 -4
  190. package/dist/src/migrator/index.d.ts.map +1 -1
  191. package/dist/src/migrator/index.js +2 -2
  192. package/dist/src/migrator/index.js.map +1 -1
  193. package/dist/src/migrator/migrator.d.ts +8 -8
  194. package/dist/src/migrator/migrator.d.ts.map +1 -1
  195. package/dist/src/migrator/migrator.js +16 -13
  196. package/dist/src/migrator/migrator.js.map +1 -1
  197. package/dist/src/migrator/schema-diff.d.ts +2 -2
  198. package/dist/src/migrator/schema-diff.d.ts.map +1 -1
  199. package/dist/src/migrator/schema-diff.js.map +1 -1
  200. package/dist/src/migrator/types.d.ts +5 -5
  201. package/dist/src/migrator/types.d.ts.map +1 -1
  202. package/dist/src/migrator/types.js +6 -7
  203. package/dist/src/migrator/types.js.map +1 -1
  204. package/dist/src/platforms/node.d.ts +1 -1
  205. package/dist/src/platforms/node.d.ts.map +1 -1
  206. package/dist/src/platforms/node.js +1 -1
  207. package/dist/src/platforms/node.js.map +1 -1
  208. package/dist/src/repository/id.d.ts +1 -1
  209. package/dist/src/repository/id.d.ts.map +1 -1
  210. package/dist/src/repository/id.js +15 -3
  211. package/dist/src/repository/id.js.map +1 -1
  212. package/dist/src/repository/repository.d.ts +3 -2
  213. package/dist/src/repository/repository.d.ts.map +1 -1
  214. package/dist/src/repository/repository.js +11 -7
  215. package/dist/src/repository/repository.js.map +1 -1
  216. package/dist/src/rule/compiler.d.ts.map +1 -1
  217. package/dist/src/rule/compiler.js +2 -0
  218. package/dist/src/rule/compiler.js.map +1 -1
  219. package/dist/src/rule/enforcer.d.ts.map +1 -1
  220. package/dist/src/rule/enforcer.js.map +1 -1
  221. package/dist/src/storage/index.d.ts +1 -1
  222. package/dist/src/storage/index.d.ts.map +1 -1
  223. package/dist/src/storage/index.js +1 -1
  224. package/dist/src/storage/index.js.map +1 -1
  225. package/dist/src/storage/local-preset.d.ts.map +1 -1
  226. package/dist/src/storage/local-preset.js.map +1 -1
  227. package/dist/src/storage/storage.d.ts +2 -2
  228. package/dist/src/storage/storage.d.ts.map +1 -1
  229. package/dist/src/storage/storage.js +8 -26
  230. package/dist/src/storage/storage.js.map +1 -1
  231. package/dist/src/telemetry/collections.d.ts +4 -0
  232. package/dist/src/telemetry/collections.d.ts.map +1 -0
  233. package/dist/src/telemetry/collections.js +19 -0
  234. package/dist/src/telemetry/collections.js.map +1 -0
  235. package/dist/src/telemetry/index.d.ts +17 -3
  236. package/dist/src/telemetry/index.d.ts.map +1 -1
  237. package/dist/src/telemetry/index.js +15 -5
  238. package/dist/src/telemetry/index.js.map +1 -1
  239. package/dist/src/telemetry/logger.d.ts +29 -2
  240. package/dist/src/telemetry/logger.d.ts.map +1 -1
  241. package/dist/src/telemetry/logger.js +52 -15
  242. package/dist/src/telemetry/logger.js.map +1 -1
  243. package/dist/src/telemetry/sqlite-logger.d.ts +36 -0
  244. package/dist/src/telemetry/sqlite-logger.d.ts.map +1 -0
  245. package/dist/src/telemetry/sqlite-logger.js +193 -0
  246. package/dist/src/telemetry/sqlite-logger.js.map +1 -0
  247. package/dist/src/telemetry/telemetry-sql-client.d.ts +11 -0
  248. package/dist/src/telemetry/telemetry-sql-client.d.ts.map +1 -0
  249. package/dist/src/telemetry/telemetry-sql-client.js +8 -0
  250. package/dist/src/telemetry/telemetry-sql-client.js.map +1 -0
  251. package/dist/src/telemetry/tracer.d.ts +16 -1
  252. package/dist/src/telemetry/tracer.d.ts.map +1 -1
  253. package/dist/src/telemetry/tracer.js +87 -70
  254. package/dist/src/telemetry/tracer.js.map +1 -1
  255. package/dist/src/telemetry/types.d.ts +11 -0
  256. package/dist/src/telemetry/types.d.ts.map +1 -0
  257. package/dist/src/telemetry/types.js +2 -0
  258. package/dist/src/telemetry/types.js.map +1 -0
  259. package/dist/src/thumbnail/index.d.ts +2 -2
  260. package/dist/src/thumbnail/index.d.ts.map +1 -1
  261. package/dist/src/thumbnail/index.js +1 -1
  262. package/dist/src/thumbnail/index.js.map +1 -1
  263. package/dist/src/thumbnail/photon.d.ts.map +1 -1
  264. package/dist/src/thumbnail/photon.js +1 -1
  265. package/dist/src/thumbnail/photon.js.map +1 -1
  266. package/dist/src/thumbnail/types.d.ts +1 -1
  267. package/dist/src/thumbnail/types.d.ts.map +1 -1
  268. package/dist/src/thumbnail/types.js +2 -2
  269. package/dist/src/thumbnail/types.js.map +1 -1
  270. package/dist/tests/app/app.test.js +101 -26
  271. package/dist/tests/app/app.test.js.map +1 -1
  272. package/dist/tests/app/builder.test.js +77 -9
  273. package/dist/tests/app/builder.test.js.map +1 -1
  274. package/dist/tests/app/define-rule.test.d.ts +2 -0
  275. package/dist/tests/app/define-rule.test.d.ts.map +1 -0
  276. package/dist/tests/app/define-rule.test.js +147 -0
  277. package/dist/tests/app/define-rule.test.js.map +1 -0
  278. package/dist/tests/cache/cached-collection.test.js +200 -40
  279. package/dist/tests/cache/cached-collection.test.js.map +1 -1
  280. package/dist/tests/cache/collection-cache.test.js +1 -1
  281. package/dist/tests/cache/collection-cache.test.js.map +1 -1
  282. package/dist/tests/collection-service/auth-credentials.test.d.ts +2 -0
  283. package/dist/tests/collection-service/auth-credentials.test.d.ts.map +1 -0
  284. package/dist/tests/collection-service/auth-credentials.test.js +172 -0
  285. package/dist/tests/collection-service/auth-credentials.test.js.map +1 -0
  286. package/dist/tests/collection-service/collection-service.test.js +374 -174
  287. package/dist/tests/collection-service/collection-service.test.js.map +1 -1
  288. package/dist/tests/collection-service/decode.test.d.ts +2 -0
  289. package/dist/tests/collection-service/decode.test.d.ts.map +1 -0
  290. package/dist/tests/collection-service/decode.test.js +37 -0
  291. package/dist/tests/collection-service/decode.test.js.map +1 -0
  292. package/dist/tests/collection-service/input-schema.test.js +162 -95
  293. package/dist/tests/collection-service/input-schema.test.js.map +1 -1
  294. package/dist/tests/config/config.test.js +15 -4
  295. package/dist/tests/config/config.test.js.map +1 -1
  296. package/dist/tests/cron/cron-integration.test.d.ts +2 -0
  297. package/dist/tests/cron/cron-integration.test.d.ts.map +1 -0
  298. package/dist/tests/cron/cron-integration.test.js +109 -0
  299. package/dist/tests/cron/cron-integration.test.js.map +1 -0
  300. package/dist/tests/cron/cron-persistence.test.d.ts +2 -0
  301. package/dist/tests/cron/cron-persistence.test.d.ts.map +1 -0
  302. package/dist/tests/cron/cron-persistence.test.js +123 -0
  303. package/dist/tests/cron/cron-persistence.test.js.map +1 -0
  304. package/dist/tests/cron/cron-service.test.d.ts +2 -0
  305. package/dist/tests/cron/cron-service.test.d.ts.map +1 -0
  306. package/dist/tests/cron/cron-service.test.js +124 -0
  307. package/dist/tests/cron/cron-service.test.js.map +1 -0
  308. package/dist/tests/crypto/crypto.test.js +2 -2
  309. package/dist/tests/crypto/crypto.test.js.map +1 -1
  310. package/dist/tests/hooks/hook-collection.test.d.ts +2 -0
  311. package/dist/tests/hooks/hook-collection.test.d.ts.map +1 -0
  312. package/dist/tests/hooks/hook-collection.test.js +110 -0
  313. package/dist/tests/hooks/hook-collection.test.js.map +1 -0
  314. package/dist/tests/hooks/hook-service.test.d.ts +2 -0
  315. package/dist/tests/hooks/hook-service.test.d.ts.map +1 -0
  316. package/dist/tests/hooks/hook-service.test.js +220 -0
  317. package/dist/tests/hooks/hook-service.test.js.map +1 -0
  318. package/dist/tests/http/cors.test.d.ts +2 -0
  319. package/dist/tests/http/cors.test.d.ts.map +1 -0
  320. package/dist/tests/http/cors.test.js +211 -0
  321. package/dist/tests/http/cors.test.js.map +1 -0
  322. package/dist/tests/http/file-serve.test.js +63 -54
  323. package/dist/tests/http/file-serve.test.js.map +1 -1
  324. package/dist/tests/http/file-token.test.js +69 -51
  325. package/dist/tests/http/file-token.test.js.map +1 -1
  326. package/dist/tests/http/ip-middleware.test.js +13 -13
  327. package/dist/tests/http/ip-middleware.test.js.map +1 -1
  328. package/dist/tests/http/port-retry.test.d.ts +2 -0
  329. package/dist/tests/http/port-retry.test.d.ts.map +1 -0
  330. package/dist/tests/http/port-retry.test.js +52 -0
  331. package/dist/tests/http/port-retry.test.js.map +1 -0
  332. package/dist/tests/http/router.test.js +260 -85
  333. package/dist/tests/http/router.test.js.map +1 -1
  334. package/dist/tests/migrator/dialect-sqlite.test.js +1 -1
  335. package/dist/tests/migrator/dialect-sqlite.test.js.map +1 -1
  336. package/dist/tests/migrator/integration.test.js +6 -6
  337. package/dist/tests/migrator/integration.test.js.map +1 -1
  338. package/dist/tests/migrator/migrator.test.js +5 -5
  339. package/dist/tests/migrator/migrator.test.js.map +1 -1
  340. package/dist/tests/migrator/schema-diff.test.js.map +1 -1
  341. package/dist/tests/repository/repository.test.js +71 -8
  342. package/dist/tests/repository/repository.test.js.map +1 -1
  343. package/dist/tests/rule/compiler.test.js +1 -1
  344. package/dist/tests/rule/compiler.test.js.map +1 -1
  345. package/dist/tests/rule/enforcer.test.js +9 -9
  346. package/dist/tests/rule/enforcer.test.js.map +1 -1
  347. package/dist/tests/storage/storage.test.js +15 -15
  348. package/dist/tests/storage/storage.test.js.map +1 -1
  349. package/dist/tests/telemetry/collections.test.d.ts +2 -0
  350. package/dist/tests/telemetry/collections.test.d.ts.map +1 -0
  351. package/dist/tests/telemetry/collections.test.js +67 -0
  352. package/dist/tests/telemetry/collections.test.js.map +1 -0
  353. package/dist/tests/telemetry/instrumentation.test.js +27 -20
  354. package/dist/tests/telemetry/instrumentation.test.js.map +1 -1
  355. package/dist/tests/telemetry/logger.test.js +38 -6
  356. package/dist/tests/telemetry/logger.test.js.map +1 -1
  357. package/dist/tests/telemetry/sqlite-logger.test.d.ts +2 -0
  358. package/dist/tests/telemetry/sqlite-logger.test.d.ts.map +1 -0
  359. package/dist/tests/telemetry/sqlite-logger.test.js +272 -0
  360. package/dist/tests/telemetry/sqlite-logger.test.js.map +1 -0
  361. package/dist/tests/telemetry/telemetry-routes.test.d.ts +2 -0
  362. package/dist/tests/telemetry/telemetry-routes.test.d.ts.map +1 -0
  363. package/dist/tests/telemetry/telemetry-routes.test.js +154 -0
  364. package/dist/tests/telemetry/telemetry-routes.test.js.map +1 -0
  365. package/dist/tests/telemetry/tracer.test.js +41 -4
  366. package/dist/tests/telemetry/tracer.test.js.map +1 -1
  367. package/dist/tests/thumbnail/photon.test.js +35 -35
  368. package/dist/tests/thumbnail/photon.test.js.map +1 -1
  369. package/dist/tests/thumbnail/thumbnail.test.js +7 -7
  370. package/dist/tests/thumbnail/thumbnail.test.js.map +1 -1
  371. package/package.json +9 -9
@@ -1,6 +1,7 @@
1
1
  import { Effect, Layer, Option } from "effect";
2
2
  import { CollectionService, makeCollectionServiceLayer } from "../collection-service/collection-service.js";
3
3
  import { CollectionCache, makeCollectionCacheLayer } from "./collection-cache.js";
4
+ import { buildCtxCacheTag } from "./ctx-key.js";
4
5
  function serializeFilterNode(node) {
5
6
  switch (node.op) {
6
7
  case "eq":
@@ -69,7 +70,8 @@ export function makeCachedCollectionServiceLayer(allCollections, config = defaul
69
70
  const cache = yield* CollectionCache;
70
71
  return CollectionService.of({
71
72
  list: (collection, cursor, perPage, ctx, filter, sort, select, expand) => {
72
- const key = `${collection.name}:${stableListKey(cursor, perPage, filter, sort, select, expand)}`;
73
+ const ctxTag = buildCtxCacheTag(collection, "list", ctx);
74
+ const key = `${collection.name}:${stableListKey(cursor, perPage, filter, sort, select, expand)}::${ctxTag}`;
73
75
  return Effect.gen(function* () {
74
76
  const cached = yield* cache.getList(key);
75
77
  yield* Effect.currentSpan.pipe(Effect.tap((span) => Effect.sync(() => span.attribute("cache.hit", Option.isSome(cached)))), Effect.ignore);
@@ -84,7 +86,8 @@ export function makeCachedCollectionServiceLayer(allCollections, config = defaul
84
86
  }));
85
87
  },
86
88
  view: (collection, id, ctx, select, expand) => {
87
- const key = stableViewKey(collection.name, id, select, expand);
89
+ const ctxTag = buildCtxCacheTag(collection, "view", ctx);
90
+ const key = `${stableViewKey(collection.name, id, select, expand)}::${ctxTag}`;
88
91
  return Effect.gen(function* () {
89
92
  const cached = yield* cache.getRecord(key);
90
93
  yield* Effect.currentSpan.pipe(Effect.tap((span) => Effect.sync(() => span.attribute("cache.hit", Option.isSome(cached)))), Effect.ignore);
@@ -98,9 +101,9 @@ export function makeCachedCollectionServiceLayer(allCollections, config = defaul
98
101
  attributes: { collection: collection.name },
99
102
  }));
100
103
  },
101
- create: (collection, data, ctx) => svc.create(collection, data, ctx).pipe(Effect.tap(() => cache.nukeListsFor(collection.name))),
102
- update: (collection, id, data, ctx) => svc.update(collection, id, data, ctx).pipe(Effect.tap(() => Effect.all([cache.invalidateRecord(collection.name, id), cache.nukeListsFor(collection.name)], { concurrency: "unbounded" }))),
103
- delete: (collection, id, ctx) => svc.delete(collection, id, ctx).pipe(Effect.tap(() => Effect.all([cache.invalidateRecord(collection.name, id), cache.nukeListsFor(collection.name)], { concurrency: "unbounded" }))),
104
+ create: (collection, data, ctx) => svc.create(collection, data, ctx).pipe(Effect.tap(() => cache.nukeListsFor(collection.name)), Effect.withSpan("cache.create", { kind: "internal", attributes: { collection: collection.name } })),
105
+ update: (collection, id, data, ctx) => svc.update(collection, id, data, ctx).pipe(Effect.tap(() => Effect.all([cache.invalidateRecord(collection.name, id), cache.nukeListsFor(collection.name)], { concurrency: "unbounded" })), Effect.withSpan("cache.update", { kind: "internal", attributes: { collection: collection.name } })),
106
+ delete: (collection, id, ctx) => svc.delete(collection, id, ctx).pipe(Effect.tap(() => Effect.all([cache.invalidateRecord(collection.name, id), cache.nukeListsFor(collection.name)], { concurrency: "unbounded" })), Effect.withSpan("cache.delete", { kind: "internal", attributes: { collection: collection.name } })),
104
107
  });
105
108
  })).pipe(Layer.provide(Layer.merge(makeCollectionServiceLayer(allCollections), makeCollectionCacheLayer(config))));
106
109
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cached-collection.js","sourceRoot":"","sources":["../../../src/cache/cached-collection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAKtD,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAA;AAE1G,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAGjF,SAAS,mBAAmB,CAAC,IAAgB;IAC3C,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC;QACV,KAAK,KAAK,CAAC;QACX,KAAK,IAAI,CAAC;QACV,KAAK,KAAK,CAAC;QACX,KAAK,IAAI,CAAC;QACV,KAAK,KAAK;YACR,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;QAC1D,KAAK,IAAI;YACP,OAAO,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAA;QACnE,KAAK,MAAM;YACT,OAAO,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,CAAA;QAC5C,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,GAAG,CAAA;QACpC,KAAK,KAAK,CAAC;QACX,KAAK,IAAI;YACP,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAA;QAC3F,KAAK,KAAK;YACR,OAAO,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;IACnD,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CACpB,GAAW,EACX,EAAU,EACV,MAAgD,EAChD,MAAgD;IAEhD,MAAM,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrE,MAAM,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrE,OAAO,GAAG,GAAG,IAAI,EAAE,IAAI,UAAU,IAAI,UAAU,EAAE,CAAA;AACnD,CAAC;AAED,SAAS,aAAa,CACpB,MAAqB,EACrB,OAAe,EACf,MAA8B,EAC9B,IAA2B,EAC3B,MAAgD,EAChD,MAAgD;IAEhD,MAAM,UAAU,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC1E,MAAM,QAAQ,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5E,MAAM,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrE,MAAM,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrE,OAAO,GAAG,MAAM,IAAI,EAAE,IAAI,OAAO,IAAI,UAAU,IAAI,QAAQ,IAAI,UAAU,IAAI,UAAU,EAAE,CAAA;AAC3F,CAAC;AAED,MAAM,aAAa,GAAgC;IACjD,WAAW,EAAE,MAAM;IACnB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,KAAK;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,gCAAgC,CAC9C,cAA+C,EAC/C,SAAsC,aAAa;IAEnD,OAAO,KAAK,CAAC,MAAM,CACjB,iBAAiB,EACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAA;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,eAAe,CAAA;QAEpC,OAAO,iBAAiB,CAAC,EAAE,CAAC;YAC1B,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACvE,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;gBAChG,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;oBACxC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAiB,EAAE,EAAE,CAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CACtE,EACD,MAAM,CAAC,MAAM,CACd,CAAA;oBACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;wBAAE,OAAO,MAAM,CAAC,KAAK,CAAA;oBAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;oBAC5F,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;oBAC/B,OAAO,IAAI,CAAA;gBACb,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE;oBAC5B,IAAI,EAAE,UAAU;oBAChB,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE;iBAC5C,CAAC,CACH,CAAA;YACH,CAAC;YAED,IAAI,EAAE,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBAC5C,MAAM,GAAG,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;gBAC9D,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;oBAC1C,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAiB,EAAE,EAAE,CAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CACtE,EACD,MAAM,CAAC,MAAM,CACd,CAAA;oBACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;wBAAE,OAAO,MAAM,CAAC,KAAK,CAAA;oBAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;oBACnE,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;oBACnC,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE;oBAC5B,IAAI,EAAE,UAAU;oBAChB,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE;iBAC5C,CAAC,CACH,CAAA;YACH,CAAC;YAED,MAAM,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAChC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CACpC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CACtD;YAEH,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CACpC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CACxC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CACd,MAAM,CAAC,GAAG,CACR,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAClF,EAAE,WAAW,EAAE,WAAW,EAAE,CAC7B,CACF,CACF;YAEH,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAC9B,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,CAClC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CACd,MAAM,CAAC,GAAG,CACR,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAClF,EAAE,WAAW,EAAE,WAAW,EAAE,CAC7B,CACF,CACF;SACJ,CAAC,CAAA;IACJ,CAAC,CAAC,CACH,CAAC,IAAI,CACJ,KAAK,CAAC,OAAO,CACX,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,cAAc,CAAC,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAC1F,CACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"cached-collection.js","sourceRoot":"","sources":["../../../src/cache/cached-collection.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { Context, Effect, Layer, Option } from "effect";
2
2
  import type { CursorPage } from "../collection-service/context.js";
3
3
  import type { RepoRecord } from "../repository/types.js";
4
4
  import type { CollectionCacheConfigValues } from "./types.js";
5
- declare const CollectionCache_base: Context.TagClass<CollectionCache, "CollectionCache", {
5
+ declare const CollectionCache_base: Context.ServiceClass<CollectionCache, "CollectionCache", {
6
6
  getRecord(key: string): Effect.Effect<Option.Option<RepoRecord>>;
7
7
  putRecord(key: string, v: RepoRecord): Effect.Effect<void>;
8
8
  invalidateRecord(col: string, id: string): Effect.Effect<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"collection-cache.d.ts","sourceRoot":"","sources":["../../../src/cache/collection-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAW,KAAK,EAAE,MAAM,EAAO,MAAM,QAAQ,CAAA;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAc,2BAA2B,EAAE,MAAM,YAAY,CAAA;;mBAKtD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;mBACjD,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;0BACpC,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;iBACjD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;iBACjD,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;sBACtC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AARlD,qBAAa,eAAgB,SAAQ,oBAUlC;CAAG;AAoCN,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,2BAA2B,GAClC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CA4B9B"}
1
+ {"version":3,"file":"collection-cache.d.ts","sourceRoot":"","sources":["../../../src/cache/collection-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAW,KAAK,EAAE,MAAM,EAAO,MAAM,QAAQ,CAAA;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,KAAK,EAAc,2BAA2B,EAAE,MAAM,YAAY,CAAA;;mBAKtD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;mBACjD,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;0BACpC,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;iBACjD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;iBACjD,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;sBACtC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;AARlD,qBAAa,eAAgB,SAAQ,oBAUf;CAAG;AAoCzB,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,2BAA2B,GAClC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CA4B9B"}
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, HashMap, Layer, Option, Ref } from "effect";
2
- export class CollectionCache extends Context.Tag("CollectionCache")() {
2
+ export class CollectionCache extends Context.Service()("CollectionCache") {
3
3
  }
4
4
  const get = (ref, key) => Ref.get(ref).pipe(Effect.map(HashMap.get(key)), Effect.map(Option.filter((e) => e.expiresAt > Date.now())), Effect.map(Option.map((e) => e.value)));
5
5
  const put = (ref, key, value, ttlMs, maxSize) => {
@@ -1 +1 @@
1
- {"version":3,"file":"collection-cache.js","sourceRoot":"","sources":["../../../src/cache/collection-cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collection-cache.js","sourceRoot":"","sources":["../../../src/cache/collection-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { AnyCollectionDef } from "@gettersethya/mira-client";
2
+ import type { RequestCtx } from "../collection-service/context.js";
3
+ /**
4
+ * Derives the portion of a cache key that captures everything a collection's
5
+ * row-level access rule for `action` could depend on in `ctx`: the admin flag,
6
+ * the authenticated identity, and only the specific request query/header keys
7
+ * the compiled rule actually references.
8
+ *
9
+ * Two requests that produce the same tag are guaranteed to be authorized
10
+ * identically by the rule — so caching by `recordKey::ctxTag` cannot let one
11
+ * requester's cached result leak to a requester the rule would otherwise deny
12
+ * or show a different field set to.
13
+ */
14
+ export declare function buildCtxCacheTag(collection: AnyCollectionDef, action: "view" | "list", ctx: RequestCtx): string;
15
+ //# sourceMappingURL=ctx-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx-key.d.ts","sourceRoot":"","sources":["../../../src/cache/ctx-key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAIjE;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,GAAG,EAAE,UAAU,GACd,MAAM,CA+BR"}
@@ -0,0 +1,37 @@
1
+ import { extractCtxRefs } from "../collection-service/where.js";
2
+ import { enforcerForAction } from "../rule/enforcer.js";
3
+ /**
4
+ * Derives the portion of a cache key that captures everything a collection's
5
+ * row-level access rule for `action` could depend on in `ctx`: the admin flag,
6
+ * the authenticated identity, and only the specific request query/header keys
7
+ * the compiled rule actually references.
8
+ *
9
+ * Two requests that produce the same tag are guaranteed to be authorized
10
+ * identically by the rule — so caching by `recordKey::ctxTag` cannot let one
11
+ * requester's cached result leak to a requester the rule would otherwise deny
12
+ * or show a different field set to.
13
+ */
14
+ export function buildCtxCacheTag(collection, action, ctx) {
15
+ if (ctx.admin === true)
16
+ return "admin";
17
+ const compiled = enforcerForAction(collection.schema, action);
18
+ if (compiled === null)
19
+ return "denied";
20
+ const refs = extractCtxRefs(compiled.sql);
21
+ const authPart = refs.authFields.length > 0
22
+ ? `auth:${refs.authFields
23
+ .map((field) => field === "collection"
24
+ ? `collection=${ctx.auth?.collection ?? ""}`
25
+ : `${field}=${String(ctx.auth?.record[field] ?? "")}`)
26
+ .join(",")}`
27
+ : "";
28
+ const queryPart = refs.queryKeys.length > 0
29
+ ? `q:${refs.queryKeys.map((key) => `${key}=${String(ctx.query[key] ?? "")}`).join(",")}`
30
+ : "";
31
+ const headerPart = refs.headerKeys.length > 0
32
+ ? `h:${refs.headerKeys.map((key) => `${key}=${String(ctx.headers[key] ?? "")}`).join(",")}`
33
+ : "";
34
+ const parts = [authPart, queryPart, headerPart].filter((p) => p.length > 0);
35
+ return parts.length > 0 ? parts.join("|") : "public";
36
+ }
37
+ //# sourceMappingURL=ctx-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx-key.js","sourceRoot":"","sources":["../../../src/cache/ctx-key.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAA4B,EAC5B,MAAuB,EACvB,GAAe;IAEf,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI;QAAE,OAAO,OAAO,CAAA;IAEtC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7D,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAA;IAEtC,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IAEzC,MAAM,QAAQ,GACZ,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,QAAQ,IAAI,CAAC,UAAU;aACpB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,KAAK,KAAK,YAAY;YACpB,CAAC,CAAC,cAAc,GAAG,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,EAAE;YAC5C,CAAC,CAAC,GAAG,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CACxD;aACA,IAAI,CAAC,GAAG,CAAC,EAAE;QAChB,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,SAAS,GACb,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACxF,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,UAAU,GACd,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC3F,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC3E,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;AACtD,CAAC"}
@@ -1,4 +1,5 @@
1
- export { CollectionCache, makeCollectionCacheLayer } from "./collection-cache.js";
2
1
  export { makeCachedCollectionServiceLayer } from "./cached-collection.js";
2
+ export { CollectionCache, makeCollectionCacheLayer } from "./collection-cache.js";
3
+ export { buildCtxCacheTag } from "./ctx-key.js";
3
4
  export type { CacheEntry, CollectionCacheConfigValues } from "./types.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAA;AACzE,YAAY,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,YAAY,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA"}
@@ -1,3 +1,4 @@
1
- export { CollectionCache, makeCollectionCacheLayer } from "./collection-cache.js";
2
1
  export { makeCachedCollectionServiceLayer } from "./cached-collection.js";
2
+ export { CollectionCache, makeCollectionCacheLayer } from "./collection-cache.js";
3
+ export { buildCtxCacheTag } from "./ctx-key.js";
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
@@ -1,13 +1,15 @@
1
- import { SqlClient } from "@effect/sql";
2
- import { Context, Effect, Layer } from "effect";
3
1
  import type { AnyCollectionDef } from "@gettersethya/mira-client";
4
2
  import type { FilterNode } from "@gettersethya/mira-client";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { SqlClient } from "effect/sql";
5
+ import { Dialect } from "../dialect/dialect.js";
6
+ import { AuthService } from "../http/auth.js";
5
7
  import { Repository } from "../repository/repository.js";
6
8
  import type { RepoRecord, SortOrder } from "../repository/types.js";
7
9
  import { FileStorage } from "../storage/storage.js";
8
10
  import type { CursorPage, RequestCtx } from "./context.js";
9
11
  import type { CollectionError } from "./errors.js";
10
- declare const CollectionService_base: Context.TagClass<CollectionService, "CollectionService", {
12
+ declare const CollectionService_base: Context.ServiceClass<CollectionService, "CollectionService", {
11
13
  list(collection: AnyCollectionDef, cursor: number | null, perPage: number, ctx: RequestCtx, filter?: FilterNode, sort?: SortOrder, select?: ReadonlyArray<string> | null, expand?: ReadonlyArray<string> | null): Effect.Effect<CursorPage, CollectionError>;
12
14
  view(collection: AnyCollectionDef, id: string, ctx: RequestCtx, select?: ReadonlyArray<string> | null, expand?: ReadonlyArray<string> | null): Effect.Effect<RepoRecord, CollectionError>;
13
15
  create(collection: AnyCollectionDef, data: RepoRecord, ctx: RequestCtx): Effect.Effect<RepoRecord, CollectionError>;
@@ -55,8 +57,8 @@ export declare class CollectionService extends CollectionService_base {
55
57
  * @see CollectionService — the service tag
56
58
  * @see makeCachedCollectionServiceLayer — wrapping layer that adds caching
57
59
  */
58
- export declare function makeCollectionServiceLayer(allCollections: ReadonlyArray<AnyCollectionDef>): Layer.Layer<CollectionService, never, Repository | SqlClient.SqlClient | FileStorage>;
60
+ export declare function makeCollectionServiceLayer(allCollections: ReadonlyArray<AnyCollectionDef>): Layer.Layer<CollectionService, never, Repository | SqlClient.SqlClient | FileStorage | Dialect | AuthService>;
59
61
  /** @deprecated Use makeCollectionServiceLayer(allCollections) */
60
- export declare const CollectionServiceLive: Layer.Layer<CollectionService, never, FileStorage | SqlClient.SqlClient | Repository>;
62
+ export declare const CollectionServiceLive: Layer.Layer<CollectionService, never, Dialect | AuthService | FileStorage | SqlClient.SqlClient | Repository>;
61
63
  export {};
62
64
  //# sourceMappingURL=collection-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection-service.d.ts","sourceRoot":"","sources":["../../../src/collection-service/collection-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,2BAA2B,CAAA;AAEnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,KAAK,EAAa,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGlD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;;qBAgChC,gBAAgB,UACpB,MAAM,GAAG,IAAI,WACZ,MAAM,OACV,UAAU,WACN,UAAU,SACZ,SAAS,WACP,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,WAC5B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;qBAG/B,gBAAgB,MACxB,MAAM,OACL,UAAU,WACN,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,WAC5B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAE1B,gBAAgB,QAAQ,UAAU,OAAO,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAGrG,gBAAgB,MACxB,MAAM,QACJ,UAAU,OACX,UAAU,GACd,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAE1B,gBAAgB,MAAM,MAAM,OAAO,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC;;AAtD3G;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,iBAAkB,SAAQ,sBAiCpC;CAAG;AAqGN;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAC9C,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC,SAAS,GAAG,WAAW,CAAC,CAyOvF;AAED,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,uFAAiC,CAAA"}
1
+ {"version":3,"file":"collection-service.d.ts","sourceRoot":"","sources":["../../../src/collection-service/collection-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,2BAA2B,CAAA;AACnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAGtC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,KAAK,EAAa,UAAU,EAAE,SAAS,EAAe,MAAM,uBAAuB,CAAA;AAE1F,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;;qBAgChC,gBAAgB,UACpB,MAAM,GAAG,IAAI,WACZ,MAAM,OACV,UAAU,WACN,UAAU,SACZ,SAAS,WACP,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,WAC5B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;qBAG/B,gBAAgB,MACxB,MAAM,OACL,UAAU,WACN,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,WAC5B,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GACpC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAE1B,gBAAgB,QAAQ,UAAU,OAAO,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAGrG,gBAAgB,MACxB,MAAM,QACJ,UAAU,OACX,UAAU,GACd,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;uBAE1B,gBAAgB,MAAM,MAAM,OAAO,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC;;AAtD3G;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,iBAAkB,SAAQ,sBAiCf;CAAG;AAwG3B;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAC9C,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC,CAub/G;AAED,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,+GAAiC,CAAA"}
@@ -1,11 +1,13 @@
1
- import { SqlClient } from "@effect/sql";
2
- import { unsafeFragment } from "@effect/sql/Statement";
3
- import { Context, Effect, Layer, Option, Schema } from "effect";
4
1
  import { filterNodeToWhereClause } from "@gettersethya/mira-client";
5
- import { enforcerForAction } from "../rule/enforcer.js";
2
+ import { Context, Effect, Layer, Option, Schema } from "effect";
3
+ import { SqlClient } from "effect/sql";
4
+ import { literal } from "effect/sql/Statement";
5
+ import { Dialect } from "../dialect/dialect.js";
6
+ import { AuthService } from "../http/auth.js";
6
7
  import { Repository } from "../repository/repository.js";
8
+ import { enforcerForAction } from "../rule/enforcer.js";
7
9
  import { FileStorage } from "../storage/storage.js";
8
- import { makeRowDecoder } from "./decode.js";
10
+ import { makeRowDecoder, makeRowEncoder } from "./decode.js";
9
11
  import { ForbiddenError, NotFoundError, ReadOnlyError, ValidationError } from "./errors.js";
10
12
  import { buildInputSchemas, parseErrToValidationError } from "./input-schema.js";
11
13
  import { andWhere, cursorClause, idClause, resolveCtxPlaceholders, resolveFieldRefs } from "./where.js";
@@ -32,17 +34,17 @@ import { andWhere, cursorClause, idClause, resolveCtxPlaceholders, resolveFieldR
32
34
  * @see makeCollectionServiceLayer — factory function
33
35
  * @see Repository — the underlying data access layer
34
36
  */
35
- export class CollectionService extends Context.Tag("CollectionService")() {
37
+ export class CollectionService extends Context.Service()("CollectionService") {
36
38
  }
37
- function resolveFields(schema, userSelect) {
39
+ function resolveFields(schema, userSelect, admin = false) {
38
40
  const nonHidden = Object.entries(schema.properties)
39
- .filter(([, p]) => !p["x-hidden"])
41
+ .filter(([, p]) => admin || !p["x-hidden"])
40
42
  .map(([k]) => k);
41
43
  if (userSelect === null)
42
44
  return nonHidden;
43
- // Intersect with non-hidden fields
45
+ // Intersect with non-hidden fields (admin bypasses hidden filter)
44
46
  const nonHiddenSet = new Set(nonHidden);
45
- const selected = userSelect.filter((f) => nonHiddenSet.has(f));
47
+ const selected = userSelect.filter((f) => admin || nonHiddenSet.has(f));
46
48
  // Always include core system fields needed for the response
47
49
  const always = new Set(["id", "created", "updated"]);
48
50
  for (const a of always) {
@@ -71,8 +73,11 @@ function resolveExpand(schema, expandFieldNames, allCollections) {
71
73
  }
72
74
  return result;
73
75
  }
76
+ // These fields are auto-generated by the system and must never be accepted from user input.
77
+ // Detected via the `x-generated` schema annotation rather than a hardcoded name list,
78
+ // so auth fields (email/password) and future additions stay user-writable.
74
79
  function rejectSystemFields(data, schema, collectionName) {
75
- const sysKeys = Object.keys(data).filter((k) => schema.properties[k]?.["x-system"] === true);
80
+ const sysKeys = Object.keys(data).filter((k) => schema.properties[k]?.["x-generated"] === true);
76
81
  if (sysKeys.length === 0)
77
82
  return Effect.void;
78
83
  return Effect.fail(new ValidationError({
@@ -126,26 +131,148 @@ export function makeCollectionServiceLayer(allCollections) {
126
131
  const repo = yield* Repository;
127
132
  const sql = yield* SqlClient.SqlClient;
128
133
  const fileStorage = yield* FileStorage;
129
- const decoderMap = new Map(allCollections.map((c) => [c.name, makeRowDecoder(c.schema)]));
134
+ const dialect = yield* Dialect;
135
+ const authService = yield* AuthService;
136
+ // Passwords on auth collections are hashed here, at the single write
137
+ // chokepoint, so every caller (HTTP router, dashboard, plugins) stores a
138
+ // hash rather than a plaintext value. On update, an empty password is
139
+ // dropped from the patch entirely so an edit form that leaves the field
140
+ // blank does not overwrite the stored hash.
141
+ const hashAuthPassword = (collection, data, dropEmpty) => Effect.gen(function* () {
142
+ if (collection.schema["x-collection-kind"] !== "auth")
143
+ return data;
144
+ if (!("password" in data))
145
+ return data;
146
+ const raw = data["password"];
147
+ if (typeof raw !== "string" || raw.length === 0) {
148
+ if (!dropEmpty)
149
+ return data;
150
+ const withoutPassword = { ...data };
151
+ delete withoutPassword["password"];
152
+ return withoutPassword;
153
+ }
154
+ const hash = yield* authService.hashPassword(raw);
155
+ return { ...data, password: hash };
156
+ });
157
+ const decoderMap = new Map(allCollections.map((c) => [c.name, makeRowDecoder(c.schema, dialect.storesBooleanAsInteger)]));
158
+ const encoderMap = new Map(allCollections.map((c) => [c.name, makeRowEncoder(c.schema, dialect.storesBooleanAsInteger)]));
130
159
  const inputSchemaMap = new Map(allCollections.map((c) => [c.name, buildInputSchemas(c)]));
131
160
  const getInputSchemas = (col) => inputSchemaMap.get(col.name) ?? buildInputSchemas(col);
132
161
  const decodeRow = (collection, record) => (decoderMap.get(collection.name) ?? Effect.succeed)(record);
162
+ const getEncoder = (collection) => encoderMap.get(collection.name) ?? ((r) => r);
163
+ // create/update return the stored row directly (no `resolveFields` pass), so
164
+ // hidden fields (auth password, seqId) must be stripped here for non-admin
165
+ // callers — matching the list/view response contract.
166
+ const stripHidden = (collection, record, admin) => {
167
+ if (admin)
168
+ return record;
169
+ const out = {};
170
+ for (const [k, v] of Object.entries(record)) {
171
+ if (collection.schema.properties[k]?.["x-hidden"] === true)
172
+ continue;
173
+ out[k] = v;
174
+ }
175
+ return out;
176
+ };
177
+ const isAuthCollection = (collection) => collection.schema["x-collection-kind"] === "auth";
178
+ const asString = (value) => (typeof value === "string" ? value : undefined);
179
+ // canManage = admin OR (auth + authenticated + manage rule matches). Evaluated
180
+ // against the incoming payload for create (emailVerified forced false so the
181
+ // rule can't be gamed by the field it guards) and against the stored record for
182
+ // update. Additive: the base create/update rule still gates access — manage only
183
+ // escalates privileges (email, emailVerified, password without oldPassword).
184
+ const canManagePayload = (collection, payload, ctx) => Effect.gen(function* () {
185
+ if (ctx.admin === true)
186
+ return true;
187
+ if (!isAuthCollection(collection) || ctx.auth === undefined)
188
+ return false;
189
+ const rule = enforcerForAction(collection.schema, "manage");
190
+ if (rule === null)
191
+ return false;
192
+ const resolved = yield* resolveCtxPlaceholders(rule, ctx, collection.name, "manage");
193
+ const bound = resolveFieldRefs(resolved, { ...payload, emailVerified: false });
194
+ const where = literal(bound.sql, bound.params);
195
+ const check = yield* sql `SELECT 1 AS ok WHERE ${where}`;
196
+ return check.length > 0;
197
+ });
198
+ const canManageRecord = (collection, id, ctx) => Effect.gen(function* () {
199
+ if (ctx.admin === true)
200
+ return true;
201
+ if (!isAuthCollection(collection) || ctx.auth === undefined)
202
+ return false;
203
+ const rule = enforcerForAction(collection.schema, "manage");
204
+ if (rule === null)
205
+ return false;
206
+ const resolved = yield* resolveCtxPlaceholders(rule, ctx, collection.name, "manage");
207
+ const allowed = yield* repo.viewFilter(collection.name, {
208
+ where: andWhere(resolved, idClause(id))
209
+ });
210
+ return allowed.length > 0;
211
+ });
212
+ const credentialError = (collection, issue) => new ValidationError({ collection: collection.name, issues: [issue] });
213
+ const verifyOldPassword = (collection, raw, existing) => Effect.gen(function* () {
214
+ const oldPassword = asString(raw["oldPassword"]);
215
+ if (oldPassword === undefined || oldPassword.length === 0) {
216
+ return yield* Effect.fail(credentialError(collection, "oldPassword is required"));
217
+ }
218
+ const stored = asString(existing["password"]);
219
+ const ok = stored !== undefined
220
+ ? yield* authService.verifyPassword(oldPassword, stored).pipe(Effect.orElseSucceed(() => false))
221
+ : false;
222
+ if (!ok) {
223
+ return yield* Effect.fail(credentialError(collection, "Missing or invalid old password"));
224
+ }
225
+ });
226
+ const enforceCreateCredentials = (collection, raw, cleaned, canManage, ctx) => Effect.gen(function* () {
227
+ if (!isAuthCollection(collection) || ctx.admin === true)
228
+ return;
229
+ const password = asString(cleaned["password"]) ?? asString(raw["password"]) ?? "";
230
+ if (password.length > 0) {
231
+ const confirm = asString(raw["passwordConfirm"]);
232
+ if (confirm === undefined || confirm !== password) {
233
+ return yield* Effect.fail(credentialError(collection, "passwordConfirm must match password"));
234
+ }
235
+ }
236
+ if (!canManage && cleaned["emailVerified"] === true) {
237
+ return yield* Effect.fail(credentialError(collection, "emailVerified cannot be set"));
238
+ }
239
+ });
240
+ const enforceUpdateCredentials = (collection, raw, cleaned, existing, canManage, ctx) => Effect.gen(function* () {
241
+ if (!isAuthCollection(collection) || ctx.admin === true)
242
+ return;
243
+ const newPassword = asString(cleaned["password"]);
244
+ const passwordChanging = newPassword !== undefined && newPassword.length > 0;
245
+ const emailChanging = "email" in cleaned && cleaned["email"] !== existing["email"];
246
+ const verifiedChanging = "emailVerified" in cleaned && Boolean(cleaned["emailVerified"]) !== Boolean(existing["emailVerified"]);
247
+ if (passwordChanging) {
248
+ const confirm = asString(raw["passwordConfirm"]);
249
+ if (confirm === undefined || confirm !== newPassword) {
250
+ return yield* Effect.fail(credentialError(collection, "passwordConfirm must match password"));
251
+ }
252
+ }
253
+ if (!canManage && (passwordChanging || emailChanging)) {
254
+ yield* verifyOldPassword(collection, raw, existing);
255
+ }
256
+ if (!canManage && verifiedChanging) {
257
+ return yield* Effect.fail(credentialError(collection, "emailVerified cannot be changed"));
258
+ }
259
+ });
133
260
  const list = (collection, cursor, perPage, ctx, filter, sort, select, expand) => Effect.gen(function* () {
134
- const ruleWhere = yield* compileRule(collection, "list", ctx);
261
+ const ruleWhere = ctx.admin ? null : yield* compileRule(collection, "list", ctx);
135
262
  const userFilter = filter !== undefined ? yield* filterNodeToWhereClause(filter, collection.schema, collection.name) : null;
136
- const where = userFilter !== null ? andWhere(ruleWhere, userFilter) : ruleWhere;
137
- const combined = cursor !== null ? andWhere(where, cursorClause(cursor)) : where;
138
- const fields = resolveFields(collection.schema, select ?? null);
263
+ const where = ruleWhere !== null && userFilter !== null ? andWhere(ruleWhere, userFilter) : (userFilter ?? ruleWhere);
264
+ const combined = cursor !== null && where !== null ? andWhere(where, cursorClause(cursor)) : where;
265
+ const fields = resolveFields(collection.schema, select ?? null, ctx.admin === true);
139
266
  const expandDefs = resolveExpand(collection.schema, expand ?? null, allCollections);
140
267
  const fieldsWithExpand = [...new Set([...fields, ...expandDefs.map((e) => e.localField)])];
141
268
  // seqId is x-hidden but must be fetched for cursor-based pagination
142
269
  const fieldsForQuery = fieldsWithExpand.includes("seqId") ? fieldsWithExpand : [...fieldsWithExpand, "seqId"];
143
- const rows = yield* repo.list(collection.name, perPage, {
144
- where: combined,
270
+ const listOpts = {
145
271
  sort: sort ?? { field: "seqId", direction: "asc" },
146
272
  fields: fieldsForQuery,
147
273
  expand: expandDefs
148
- });
274
+ };
275
+ const rows = yield* repo.list(collection.name, perPage, combined !== null ? { ...listOpts, where: combined } : listOpts);
149
276
  const lastRow = rows.items.at(-1);
150
277
  const rawSeqId = lastRow?.["seqId"];
151
278
  const lastSeqId = typeof rawSeqId === "number" ? rawSeqId : null;
@@ -162,9 +289,9 @@ export function makeCollectionServiceLayer(allCollections) {
162
289
  attributes: { collection: collection.name }
163
290
  }));
164
291
  const view = (collection, id, ctx, select, expand) => Effect.gen(function* () {
165
- const ruleWhere = yield* compileRule(collection, "view", ctx);
166
- const combined = andWhere(ruleWhere, idClause(id));
167
- const fields = resolveFields(collection.schema, select ?? null);
292
+ const ruleWhere = ctx.admin ? null : yield* compileRule(collection, "view", ctx);
293
+ const combined = ruleWhere !== null ? andWhere(ruleWhere, idClause(id)) : idClause(id);
294
+ const fields = resolveFields(collection.schema, select ?? null, ctx.admin === true);
168
295
  const expandDefs = resolveExpand(collection.schema, expand ?? null, allCollections);
169
296
  const fieldsWithExpand = [...new Set([...fields, ...expandDefs.map((e) => e.localField)])];
170
297
  const rows = yield* repo.viewFilter(collection.name, {
@@ -186,17 +313,21 @@ export function makeCollectionServiceLayer(allCollections) {
186
313
  }
187
314
  yield* rejectSystemFields(data, collection.schema, collection.name);
188
315
  const schemas = getInputSchemas(collection);
189
- const cleaned = yield* Schema.decodeUnknown(schemas.create)(data).pipe(Effect.mapError(parseErrToValidationError(collection.name)));
190
- const ruleWhere = yield* compileRule(collection, "create", ctx);
191
- // Pre-check: evaluate the create rule against the payload (no table needed).
192
- const payloadBound = resolveFieldRefs(ruleWhere, cleaned);
193
- const where = unsafeFragment(payloadBound.sql, payloadBound.params);
194
- const check = yield* sql `SELECT 1 AS ok WHERE ${where}`;
195
- if (check.length === 0) {
196
- return yield* new ForbiddenError({ collection: collection.name, action: "create" });
316
+ const cleaned = yield* Schema.decodeUnknownEffect(schemas.create)(data).pipe(Effect.mapError(parseErrToValidationError(collection.name)));
317
+ if (!ctx.admin) {
318
+ const ruleWhere = yield* compileRule(collection, "create", ctx);
319
+ // Pre-check: evaluate the create rule against the payload (no table needed).
320
+ const payloadBound = resolveFieldRefs(ruleWhere, cleaned);
321
+ const where = literal(payloadBound.sql, payloadBound.params);
322
+ const check = yield* sql `SELECT 1 AS ok WHERE ${where}`;
323
+ if (check.length === 0) {
324
+ return yield* new ForbiddenError({ collection: collection.name, action: "create" });
325
+ }
197
326
  }
198
- const row = yield* repo.create(collection.name, cleaned);
199
- return yield* decodeRow(collection, row);
327
+ const canManage = yield* canManagePayload(collection, cleaned, ctx);
328
+ yield* enforceCreateCredentials(collection, data, cleaned, canManage, ctx);
329
+ const row = yield* repo.create(collection.name, getEncoder(collection)(yield* hashAuthPassword(collection, cleaned, false)));
330
+ return stripHidden(collection, yield* decodeRow(collection, row), ctx.admin === true);
200
331
  }).pipe(Effect.withSpan("collection.create", {
201
332
  kind: "internal",
202
333
  attributes: { collection: collection.name }
@@ -207,28 +338,38 @@ export function makeCollectionServiceLayer(allCollections) {
207
338
  }
208
339
  yield* rejectSystemFields(data, collection.schema, collection.name);
209
340
  const schemas = getInputSchemas(collection);
210
- const cleaned = yield* Schema.decodeUnknown(schemas.update)(data).pipe(Effect.mapError(parseErrToValidationError(collection.name)));
211
- const ruleWhere = yield* compileRule(collection, "update", ctx);
212
- // Existence check first — distinguish NotFound from Forbidden
341
+ const cleaned = yield* Schema.decodeUnknownEffect(schemas.update)(data).pipe(Effect.mapError(parseErrToValidationError(collection.name)));
342
+ // If the collection has no rules at all, deny immediately (don't leak existence)
343
+ if (!ctx.admin) {
344
+ const enforcerResult = enforcerForAction(collection.schema, "update");
345
+ if (enforcerResult === null) {
346
+ return yield* new ForbiddenError({ collection: collection.name, action: "update" });
347
+ }
348
+ }
213
349
  const existing = yield* repo.view(collection.name, id);
214
350
  if (Option.isNone(existing)) {
215
351
  return yield* new NotFoundError({ collection: collection.name, id });
216
352
  }
217
- // Rule check against this specific row
218
- const combined = andWhere(ruleWhere, idClause(id));
219
- const allowed = yield* repo.viewFilter(collection.name, { where: combined });
220
- if (allowed.length === 0) {
221
- return yield* new ForbiddenError({ collection: collection.name, action: "update" });
353
+ if (!ctx.admin) {
354
+ const ruleWhere = yield* compileRule(collection, "update", ctx);
355
+ // Rule check against this specific row
356
+ const combined = andWhere(ruleWhere, idClause(id));
357
+ const allowed = yield* repo.viewFilter(collection.name, { where: combined });
358
+ if (allowed.length === 0) {
359
+ return yield* new ForbiddenError({ collection: collection.name, action: "update" });
360
+ }
222
361
  }
223
- const updated = yield* repo.update(collection.name, id, cleaned);
362
+ const canManage = yield* canManageRecord(collection, id, ctx);
363
+ yield* enforceUpdateCredentials(collection, data, cleaned, existing.value, canManage, ctx);
364
+ const updated = yield* repo.update(collection.name, id, getEncoder(collection)(yield* hashAuthPassword(collection, cleaned, true)));
224
365
  // Best-effort: delete old files and their thumbnails for any replaced file fields.
225
366
  const oldKeys = extractReplacedFileKeys(existing.value, cleaned, collection.schema);
226
367
  yield* Effect.forEach(oldKeys, (key) => Effect.gen(function* () {
227
- yield* fileStorage.delete(key).pipe(Effect.orElse(() => Effect.void));
368
+ yield* fileStorage.delete(key).pipe(Effect.catch(() => Effect.void));
228
369
  const thumbKeys = yield* fileStorage.list(`_thumbs/${key}/`).pipe(Effect.orElseSucceed(() => []));
229
- yield* Effect.forEach(thumbKeys, (tk) => fileStorage.delete(tk).pipe(Effect.orElse(() => Effect.void)), { concurrency: "unbounded" });
370
+ yield* Effect.forEach(thumbKeys, (tk) => fileStorage.delete(tk).pipe(Effect.catch(() => Effect.void)), { concurrency: "unbounded" });
230
371
  }), { concurrency: "unbounded" });
231
- return yield* decodeRow(collection, Option.getOrElse(updated, () => existing.value));
372
+ return stripHidden(collection, yield* decodeRow(collection, Option.getOrElse(updated, () => existing.value)), ctx.admin === true);
232
373
  }).pipe(Effect.withSpan("collection.update", {
233
374
  kind: "internal",
234
375
  attributes: { collection: collection.name }
@@ -237,23 +378,32 @@ export function makeCollectionServiceLayer(allCollections) {
237
378
  if (collection.schema["x-collection-kind"] === "view") {
238
379
  return yield* new ReadOnlyError({ collection: collection.name });
239
380
  }
240
- const ruleWhere = yield* compileRule(collection, "delete", ctx);
381
+ // If the collection has no rules at all, deny immediately (don't leak existence)
382
+ if (!ctx.admin) {
383
+ const enforcerResult = enforcerForAction(collection.schema, "delete");
384
+ if (enforcerResult === null) {
385
+ return yield* new ForbiddenError({ collection: collection.name, action: "delete" });
386
+ }
387
+ }
241
388
  const existing = yield* repo.view(collection.name, id);
242
389
  if (Option.isNone(existing)) {
243
390
  return yield* new NotFoundError({ collection: collection.name, id });
244
391
  }
245
- const combined = andWhere(ruleWhere, idClause(id));
246
- const allowed = yield* repo.viewFilter(collection.name, { where: combined });
247
- if (allowed.length === 0) {
248
- return yield* new ForbiddenError({ collection: collection.name, action: "delete" });
392
+ if (!ctx.admin) {
393
+ const ruleWhere = yield* compileRule(collection, "delete", ctx);
394
+ const combined = andWhere(ruleWhere, idClause(id));
395
+ const allowed = yield* repo.viewFilter(collection.name, { where: combined });
396
+ if (allowed.length === 0) {
397
+ return yield* new ForbiddenError({ collection: collection.name, action: "delete" });
398
+ }
249
399
  }
250
400
  yield* repo.delete(collection.name, id);
251
401
  // Best-effort: delete files and their thumbnails after the record is gone.
252
402
  const keys = extractFileKeys(existing.value, collection.schema);
253
403
  yield* Effect.forEach(keys, (key) => Effect.gen(function* () {
254
- yield* fileStorage.delete(key).pipe(Effect.orElse(() => Effect.void));
404
+ yield* fileStorage.delete(key).pipe(Effect.catch(() => Effect.void));
255
405
  const thumbKeys = yield* fileStorage.list(`_thumbs/${key}/`).pipe(Effect.orElseSucceed(() => []));
256
- yield* Effect.forEach(thumbKeys, (tk) => fileStorage.delete(tk).pipe(Effect.orElse(() => Effect.void)), { concurrency: "unbounded" });
406
+ yield* Effect.forEach(thumbKeys, (tk) => fileStorage.delete(tk).pipe(Effect.catch(() => Effect.void)), { concurrency: "unbounded" });
257
407
  }), { concurrency: "unbounded" });
258
408
  }).pipe(Effect.withSpan("collection.delete", {
259
409
  kind: "internal",