@crowdsource.you/core 1.2.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 (339) hide show
  1. package/README.md +571 -0
  2. package/dist/cases.d.ts +66 -0
  3. package/dist/cases.d.ts.map +1 -0
  4. package/dist/cases.js +79 -0
  5. package/dist/cases.js.map +1 -0
  6. package/dist/client.d.ts +90 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +125 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/communityNotes.d.ts +49 -0
  11. package/dist/communityNotes.d.ts.map +1 -0
  12. package/dist/communityNotes.js +104 -0
  13. package/dist/communityNotes.js.map +1 -0
  14. package/dist/credential.d.ts +58 -0
  15. package/dist/credential.d.ts.map +1 -0
  16. package/dist/credential.js +71 -0
  17. package/dist/credential.js.map +1 -0
  18. package/dist/defaults.d.ts +61 -0
  19. package/dist/defaults.d.ts.map +1 -0
  20. package/dist/defaults.js +82 -0
  21. package/dist/defaults.js.map +1 -0
  22. package/dist/digest.d.ts +44 -0
  23. package/dist/digest.d.ts.map +1 -0
  24. package/dist/digest.js +79 -0
  25. package/dist/digest.js.map +1 -0
  26. package/dist/envelope.d.ts +143 -0
  27. package/dist/envelope.d.ts.map +1 -0
  28. package/dist/envelope.js +258 -0
  29. package/dist/envelope.js.map +1 -0
  30. package/dist/errors.d.ts +90 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +151 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/esm/cases.js +74 -0
  35. package/dist/esm/cases.js.map +1 -0
  36. package/dist/esm/client.js +121 -0
  37. package/dist/esm/client.js.map +1 -0
  38. package/dist/esm/communityNotes.js +100 -0
  39. package/dist/esm/communityNotes.js.map +1 -0
  40. package/dist/esm/credential.js +67 -0
  41. package/dist/esm/credential.js.map +1 -0
  42. package/dist/esm/defaults.js +77 -0
  43. package/dist/esm/defaults.js.map +1 -0
  44. package/dist/esm/digest.js +74 -0
  45. package/dist/esm/digest.js.map +1 -0
  46. package/dist/esm/envelope.js +252 -0
  47. package/dist/esm/envelope.js.map +1 -0
  48. package/dist/esm/errors.js +140 -0
  49. package/dist/esm/errors.js.map +1 -0
  50. package/dist/esm/express/index.js +29 -0
  51. package/dist/esm/express/index.js.map +1 -0
  52. package/dist/esm/express/middleware.js +293 -0
  53. package/dist/esm/express/middleware.js.map +1 -0
  54. package/dist/esm/express/store.js +69 -0
  55. package/dist/esm/express/store.js.map +1 -0
  56. package/dist/esm/express/verify.js +133 -0
  57. package/dist/esm/express/verify.js.map +1 -0
  58. package/dist/esm/index.js +57 -0
  59. package/dist/esm/index.js.map +1 -0
  60. package/dist/esm/outbox/client.js +43 -0
  61. package/dist/esm/outbox/client.js.map +1 -0
  62. package/dist/esm/outbox/decision.js +153 -0
  63. package/dist/esm/outbox/decision.js.map +1 -0
  64. package/dist/esm/outbox/delivery.js +129 -0
  65. package/dist/esm/outbox/delivery.js.map +1 -0
  66. package/dist/esm/outbox/enforcement/executor.js +219 -0
  67. package/dist/esm/outbox/enforcement/executor.js.map +1 -0
  68. package/dist/esm/outbox/enforcement/planner.js +326 -0
  69. package/dist/esm/outbox/enforcement/planner.js.map +1 -0
  70. package/dist/esm/outbox/evidence.js +173 -0
  71. package/dist/esm/outbox/evidence.js.map +1 -0
  72. package/dist/esm/outbox/inbound.js +87 -0
  73. package/dist/esm/outbox/inbound.js.map +1 -0
  74. package/dist/esm/outbox/index.js +71 -0
  75. package/dist/esm/outbox/index.js.map +1 -0
  76. package/dist/esm/outbox/intake.js +140 -0
  77. package/dist/esm/outbox/intake.js.map +1 -0
  78. package/dist/esm/outbox/integration.js +116 -0
  79. package/dist/esm/outbox/integration.js.map +1 -0
  80. package/dist/esm/outbox/outbox/dispatcher.js +114 -0
  81. package/dist/esm/outbox/outbox/dispatcher.js.map +1 -0
  82. package/dist/esm/outbox/outbox/service.js +271 -0
  83. package/dist/esm/outbox/outbox/service.js.map +1 -0
  84. package/dist/esm/outbox/postgres/index.js +41 -0
  85. package/dist/esm/outbox/postgres/index.js.map +1 -0
  86. package/dist/esm/outbox/postgres/registries.js +155 -0
  87. package/dist/esm/outbox/postgres/registries.js.map +1 -0
  88. package/dist/esm/outbox/postgres/reportColumns.js +191 -0
  89. package/dist/esm/outbox/postgres/reportColumns.js.map +1 -0
  90. package/dist/esm/outbox/postgres/store/enforcement.js +158 -0
  91. package/dist/esm/outbox/postgres/store/enforcement.js.map +1 -0
  92. package/dist/esm/outbox/postgres/store/events.js +101 -0
  93. package/dist/esm/outbox/postgres/store/events.js.map +1 -0
  94. package/dist/esm/outbox/postgres/store/index.js +59 -0
  95. package/dist/esm/outbox/postgres/store/index.js.map +1 -0
  96. package/dist/esm/outbox/postgres/store/outbox.js +207 -0
  97. package/dist/esm/outbox/postgres/store/outbox.js.map +1 -0
  98. package/dist/esm/outbox/postgres/store/reports.js +231 -0
  99. package/dist/esm/outbox/postgres/store/reports.js.map +1 -0
  100. package/dist/esm/outbox/postgres/store/transaction.js +29 -0
  101. package/dist/esm/outbox/postgres/store/transaction.js.map +1 -0
  102. package/dist/esm/outbox/postgres/tables.js +270 -0
  103. package/dist/esm/outbox/postgres/tables.js.map +1 -0
  104. package/dist/esm/outbox/reconciliation.js +157 -0
  105. package/dist/esm/outbox/reconciliation.js.map +1 -0
  106. package/dist/esm/outbox/reportStatus.js +22 -0
  107. package/dist/esm/outbox/reportStatus.js.map +1 -0
  108. package/dist/esm/outbox/retention.js +33 -0
  109. package/dist/esm/outbox/retention.js.map +1 -0
  110. package/dist/esm/outbox/store/types.js +30 -0
  111. package/dist/esm/outbox/store/types.js.map +1 -0
  112. package/dist/esm/outbox/types.js +23 -0
  113. package/dist/esm/outbox/types.js.map +1 -0
  114. package/dist/esm/outbox/webhook.js +145 -0
  115. package/dist/esm/outbox/webhook.js.map +1 -0
  116. package/dist/esm/package.json +1 -0
  117. package/dist/esm/reports.js +74 -0
  118. package/dist/esm/reports.js.map +1 -0
  119. package/dist/esm/testing/fixtures.js +132 -0
  120. package/dist/esm/testing/fixtures.js.map +1 -0
  121. package/dist/esm/testing/index.js +33 -0
  122. package/dist/esm/testing/index.js.map +1 -0
  123. package/dist/esm/testing/sandbox.js +337 -0
  124. package/dist/esm/testing/sandbox.js.map +1 -0
  125. package/dist/esm/testing/webhook-simulator.js +93 -0
  126. package/dist/esm/testing/webhook-simulator.js.map +1 -0
  127. package/dist/esm/transport.js +177 -0
  128. package/dist/esm/transport.js.map +1 -0
  129. package/dist/esm/webhookEndpoints.js +139 -0
  130. package/dist/esm/webhookEndpoints.js.map +1 -0
  131. package/dist/express/index.d.ts +32 -0
  132. package/dist/express/index.d.ts.map +1 -0
  133. package/dist/express/index.js +40 -0
  134. package/dist/express/index.js.map +1 -0
  135. package/dist/express/middleware.d.ts +97 -0
  136. package/dist/express/middleware.d.ts.map +1 -0
  137. package/dist/express/middleware.js +298 -0
  138. package/dist/express/middleware.js.map +1 -0
  139. package/dist/express/store.d.ts +45 -0
  140. package/dist/express/store.d.ts.map +1 -0
  141. package/dist/express/store.js +72 -0
  142. package/dist/express/store.js.map +1 -0
  143. package/dist/express/verify.d.ts +86 -0
  144. package/dist/express/verify.d.ts.map +1 -0
  145. package/dist/express/verify.js +138 -0
  146. package/dist/express/verify.js.map +1 -0
  147. package/dist/index.d.ts +67 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +89 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/outbox/client.d.ts +35 -0
  152. package/dist/outbox/client.d.ts.map +1 -0
  153. package/dist/outbox/client.js +46 -0
  154. package/dist/outbox/client.js.map +1 -0
  155. package/dist/outbox/decision.d.ts +36 -0
  156. package/dist/outbox/decision.d.ts.map +1 -0
  157. package/dist/outbox/decision.js +159 -0
  158. package/dist/outbox/decision.js.map +1 -0
  159. package/dist/outbox/delivery.d.ts +50 -0
  160. package/dist/outbox/delivery.d.ts.map +1 -0
  161. package/dist/outbox/delivery.js +135 -0
  162. package/dist/outbox/delivery.js.map +1 -0
  163. package/dist/outbox/enforcement/executor.d.ts +26 -0
  164. package/dist/outbox/enforcement/executor.d.ts.map +1 -0
  165. package/dist/outbox/enforcement/executor.js +222 -0
  166. package/dist/outbox/enforcement/executor.js.map +1 -0
  167. package/dist/outbox/enforcement/planner.d.ts +50 -0
  168. package/dist/outbox/enforcement/planner.d.ts.map +1 -0
  169. package/dist/outbox/enforcement/planner.js +333 -0
  170. package/dist/outbox/enforcement/planner.js.map +1 -0
  171. package/dist/outbox/evidence.d.ts +114 -0
  172. package/dist/outbox/evidence.d.ts.map +1 -0
  173. package/dist/outbox/evidence.js +181 -0
  174. package/dist/outbox/evidence.js.map +1 -0
  175. package/dist/outbox/inbound.d.ts +78 -0
  176. package/dist/outbox/inbound.d.ts.map +1 -0
  177. package/dist/outbox/inbound.js +91 -0
  178. package/dist/outbox/inbound.js.map +1 -0
  179. package/dist/outbox/index.d.ts +79 -0
  180. package/dist/outbox/index.d.ts.map +1 -0
  181. package/dist/outbox/index.js +98 -0
  182. package/dist/outbox/index.js.map +1 -0
  183. package/dist/outbox/intake.d.ts +62 -0
  184. package/dist/outbox/intake.d.ts.map +1 -0
  185. package/dist/outbox/intake.js +145 -0
  186. package/dist/outbox/intake.js.map +1 -0
  187. package/dist/outbox/integration.d.ts +62 -0
  188. package/dist/outbox/integration.d.ts.map +1 -0
  189. package/dist/outbox/integration.js +119 -0
  190. package/dist/outbox/integration.js.map +1 -0
  191. package/dist/outbox/outbox/dispatcher.d.ts +26 -0
  192. package/dist/outbox/outbox/dispatcher.d.ts.map +1 -0
  193. package/dist/outbox/outbox/dispatcher.js +119 -0
  194. package/dist/outbox/outbox/dispatcher.js.map +1 -0
  195. package/dist/outbox/outbox/service.d.ts +124 -0
  196. package/dist/outbox/outbox/service.d.ts.map +1 -0
  197. package/dist/outbox/outbox/service.js +279 -0
  198. package/dist/outbox/outbox/service.js.map +1 -0
  199. package/dist/outbox/postgres/index.d.ts +44 -0
  200. package/dist/outbox/postgres/index.d.ts.map +1 -0
  201. package/dist/outbox/postgres/index.js +51 -0
  202. package/dist/outbox/postgres/index.js.map +1 -0
  203. package/dist/outbox/postgres/registries.d.ts +69 -0
  204. package/dist/outbox/postgres/registries.d.ts.map +1 -0
  205. package/dist/outbox/postgres/registries.js +159 -0
  206. package/dist/outbox/postgres/registries.js.map +1 -0
  207. package/dist/outbox/postgres/reportColumns.d.ts +154 -0
  208. package/dist/outbox/postgres/reportColumns.d.ts.map +1 -0
  209. package/dist/outbox/postgres/reportColumns.js +195 -0
  210. package/dist/outbox/postgres/reportColumns.js.map +1 -0
  211. package/dist/outbox/postgres/store/enforcement.d.ts +33 -0
  212. package/dist/outbox/postgres/store/enforcement.d.ts.map +1 -0
  213. package/dist/outbox/postgres/store/enforcement.js +161 -0
  214. package/dist/outbox/postgres/store/enforcement.js.map +1 -0
  215. package/dist/outbox/postgres/store/events.d.ts +46 -0
  216. package/dist/outbox/postgres/store/events.d.ts.map +1 -0
  217. package/dist/outbox/postgres/store/events.js +104 -0
  218. package/dist/outbox/postgres/store/events.js.map +1 -0
  219. package/dist/outbox/postgres/store/index.d.ts +27 -0
  220. package/dist/outbox/postgres/store/index.d.ts.map +1 -0
  221. package/dist/outbox/postgres/store/index.js +62 -0
  222. package/dist/outbox/postgres/store/index.js.map +1 -0
  223. package/dist/outbox/postgres/store/outbox.d.ts +8 -0
  224. package/dist/outbox/postgres/store/outbox.d.ts.map +1 -0
  225. package/dist/outbox/postgres/store/outbox.js +210 -0
  226. package/dist/outbox/postgres/store/outbox.js.map +1 -0
  227. package/dist/outbox/postgres/store/reports.d.ts +69 -0
  228. package/dist/outbox/postgres/store/reports.d.ts.map +1 -0
  229. package/dist/outbox/postgres/store/reports.js +234 -0
  230. package/dist/outbox/postgres/store/reports.js.map +1 -0
  231. package/dist/outbox/postgres/store/transaction.d.ts +49 -0
  232. package/dist/outbox/postgres/store/transaction.d.ts.map +1 -0
  233. package/dist/outbox/postgres/store/transaction.js +32 -0
  234. package/dist/outbox/postgres/store/transaction.js.map +1 -0
  235. package/dist/outbox/postgres/tables.d.ts +737 -0
  236. package/dist/outbox/postgres/tables.d.ts.map +1 -0
  237. package/dist/outbox/postgres/tables.js +273 -0
  238. package/dist/outbox/postgres/tables.js.map +1 -0
  239. package/dist/outbox/reconciliation.d.ts +49 -0
  240. package/dist/outbox/reconciliation.d.ts.map +1 -0
  241. package/dist/outbox/reconciliation.js +162 -0
  242. package/dist/outbox/reconciliation.js.map +1 -0
  243. package/dist/outbox/reportStatus.d.ts +12 -0
  244. package/dist/outbox/reportStatus.d.ts.map +1 -0
  245. package/dist/outbox/reportStatus.js +25 -0
  246. package/dist/outbox/reportStatus.js.map +1 -0
  247. package/dist/outbox/retention.d.ts +33 -0
  248. package/dist/outbox/retention.d.ts.map +1 -0
  249. package/dist/outbox/retention.js +36 -0
  250. package/dist/outbox/retention.js.map +1 -0
  251. package/dist/outbox/store/types.d.ts +466 -0
  252. package/dist/outbox/store/types.d.ts.map +1 -0
  253. package/dist/outbox/store/types.js +31 -0
  254. package/dist/outbox/store/types.js.map +1 -0
  255. package/dist/outbox/types.d.ts +660 -0
  256. package/dist/outbox/types.d.ts.map +1 -0
  257. package/dist/outbox/types.js +24 -0
  258. package/dist/outbox/types.js.map +1 -0
  259. package/dist/outbox/webhook.d.ts +15 -0
  260. package/dist/outbox/webhook.d.ts.map +1 -0
  261. package/dist/outbox/webhook.js +148 -0
  262. package/dist/outbox/webhook.js.map +1 -0
  263. package/dist/reports.d.ts +73 -0
  264. package/dist/reports.d.ts.map +1 -0
  265. package/dist/reports.js +78 -0
  266. package/dist/reports.js.map +1 -0
  267. package/dist/testing/fixtures.d.ts +62 -0
  268. package/dist/testing/fixtures.d.ts.map +1 -0
  269. package/dist/testing/fixtures.js +137 -0
  270. package/dist/testing/fixtures.js.map +1 -0
  271. package/dist/testing/index.d.ts +36 -0
  272. package/dist/testing/index.d.ts.map +1 -0
  273. package/dist/testing/index.js +43 -0
  274. package/dist/testing/index.js.map +1 -0
  275. package/dist/testing/sandbox.d.ts +109 -0
  276. package/dist/testing/sandbox.d.ts.map +1 -0
  277. package/dist/testing/sandbox.js +342 -0
  278. package/dist/testing/sandbox.js.map +1 -0
  279. package/dist/testing/webhook-simulator.d.ts +78 -0
  280. package/dist/testing/webhook-simulator.d.ts.map +1 -0
  281. package/dist/testing/webhook-simulator.js +98 -0
  282. package/dist/testing/webhook-simulator.js.map +1 -0
  283. package/dist/transport.d.ts +59 -0
  284. package/dist/transport.d.ts.map +1 -0
  285. package/dist/transport.js +181 -0
  286. package/dist/transport.js.map +1 -0
  287. package/dist/webhookEndpoints.d.ts +147 -0
  288. package/dist/webhookEndpoints.d.ts.map +1 -0
  289. package/dist/webhookEndpoints.js +143 -0
  290. package/dist/webhookEndpoints.js.map +1 -0
  291. package/package.json +127 -0
  292. package/src/cases.ts +119 -0
  293. package/src/client.ts +202 -0
  294. package/src/communityNotes.ts +194 -0
  295. package/src/credential.ts +100 -0
  296. package/src/defaults.ts +87 -0
  297. package/src/digest.ts +91 -0
  298. package/src/envelope.ts +432 -0
  299. package/src/errors.ts +165 -0
  300. package/src/express/index.ts +43 -0
  301. package/src/express/middleware.ts +387 -0
  302. package/src/express/store.ts +85 -0
  303. package/src/express/verify.ts +166 -0
  304. package/src/index.ts +107 -0
  305. package/src/outbox/client.ts +75 -0
  306. package/src/outbox/decision.ts +209 -0
  307. package/src/outbox/delivery.ts +163 -0
  308. package/src/outbox/enforcement/executor.ts +288 -0
  309. package/src/outbox/enforcement/planner.ts +377 -0
  310. package/src/outbox/evidence.ts +231 -0
  311. package/src/outbox/inbound.ts +140 -0
  312. package/src/outbox/index.ts +160 -0
  313. package/src/outbox/intake.ts +175 -0
  314. package/src/outbox/integration.ts +205 -0
  315. package/src/outbox/outbox/dispatcher.ts +131 -0
  316. package/src/outbox/outbox/service.ts +444 -0
  317. package/src/outbox/postgres/index.ts +59 -0
  318. package/src/outbox/postgres/registries.ts +177 -0
  319. package/src/outbox/postgres/reportColumns.ts +281 -0
  320. package/src/outbox/postgres/store/enforcement.ts +186 -0
  321. package/src/outbox/postgres/store/events.ts +112 -0
  322. package/src/outbox/postgres/store/index.ts +72 -0
  323. package/src/outbox/postgres/store/outbox.ts +273 -0
  324. package/src/outbox/postgres/store/reports.ts +349 -0
  325. package/src/outbox/postgres/store/transaction.ts +64 -0
  326. package/src/outbox/postgres/tables.ts +339 -0
  327. package/src/outbox/reconciliation.ts +199 -0
  328. package/src/outbox/reportStatus.ts +24 -0
  329. package/src/outbox/retention.ts +34 -0
  330. package/src/outbox/store/types.ts +528 -0
  331. package/src/outbox/types.ts +753 -0
  332. package/src/outbox/webhook.ts +165 -0
  333. package/src/reports.ts +138 -0
  334. package/src/testing/fixtures.ts +183 -0
  335. package/src/testing/index.ts +57 -0
  336. package/src/testing/sandbox.ts +469 -0
  337. package/src/testing/webhook-simulator.ts +166 -0
  338. package/src/transport.ts +250 -0
  339. package/src/webhookEndpoints.ts +256 -0
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModerationTaxonomyError = exports.ModerationSubjectUnsupportedError = void 0;
4
+ exports.snapshotHash = snapshotHash;
5
+ exports.createSubjectRegistry = createSubjectRegistry;
6
+ exports.buildModerationReportInput = buildModerationReportInput;
7
+ const crypto_1 = require("crypto");
8
+ /**
9
+ * Turning a stored report into the thing the SDK delivers.
10
+ *
11
+ * This is NOT a case-envelope builder, and the difference matters enough to
12
+ * name: `@crowdsource.you/core` builds the Case Envelope, and it deliberately does
13
+ * not export the function that does it. What this module produces is the SDK's
14
+ * `ReportInput` — a description of the material — and the SDK derives the
15
+ * envelope from it: resource ids, relations, digests, pseudonymous principal
16
+ * refs, the identity binding proof, the pinned policy version, the privacy terms
17
+ * and the idempotency key.
18
+ *
19
+ * That is not a technicality. Those derived values are exactly what the case
20
+ * dedup key is computed over, so an application that composed its own envelope
21
+ * would be the reason two reporters about one object opened two cases — and "one
22
+ * penalty per incident" would fail in production with nothing failing in a test.
23
+ * Building the description and letting the SDK build the document is what keeps
24
+ * that property true for every application at once.
25
+ *
26
+ * So this module does three things and no more: ask the registry for a snapshot
27
+ * of the reported object, translate the reporter's categories into allegations,
28
+ * and assemble both with the report's own identity.
29
+ */
30
+ /**
31
+ * The material could not be described, because nothing can describe it.
32
+ *
33
+ * This is a DEFECT, not a state, and it should be unreachable. A report whose
34
+ * type has no subject provider never gets a delivery event in the first place —
35
+ * intake decides that from the same registry this module reads — so an event
36
+ * that arrives here has been created by something that bypassed intake, or by a
37
+ * deployment where a provider was removed while its reports were still in
38
+ * flight.
39
+ *
40
+ * `retryable: false` therefore dead-letters the outbox event, so the
41
+ * reconciliation sweep counts it and a human looks. The alternative — writing a
42
+ * local state — would file a genuine defect in the one place that looks
43
+ * identical to the deliberate local-only reports, and nothing would ever alert
44
+ * on it.
45
+ *
46
+ * Separate from "the object is gone": a deleted object is a fact about the world
47
+ * and closes the report normally.
48
+ */
49
+ class ModerationSubjectUnsupportedError extends Error {
50
+ constructor(reportedType) {
51
+ super(`No moderation subject provider is registered for '${reportedType}'.`);
52
+ this.retryable = false;
53
+ this.name = 'ModerationSubjectUnsupportedError';
54
+ }
55
+ }
56
+ exports.ModerationSubjectUnsupportedError = ModerationSubjectUnsupportedError;
57
+ /**
58
+ * The application's taxonomy produced no allegation for a report.
59
+ *
60
+ * Not retryable and never silently defaulted. A report with no allegation is not
61
+ * a report, and substituting `other.unclassifiable` here would put a claim in
62
+ * front of a jury that no reporter made and that no version of the mapping
63
+ * records — the taxonomy is the application's to fix, and dead-lettering is what
64
+ * makes somebody fix it.
65
+ */
66
+ class ModerationTaxonomyError extends Error {
67
+ constructor(categories) {
68
+ super(`The report taxonomy produced no allegation for categories [${categories.join(', ')}]. ` +
69
+ 'Map every category to a code; use `other.unclassifiable` for one the universal taxonomy cannot name.');
70
+ this.retryable = false;
71
+ this.name = 'ModerationTaxonomyError';
72
+ }
73
+ }
74
+ exports.ModerationTaxonomyError = ModerationTaxonomyError;
75
+ /**
76
+ * SHA-256 of the snapshot, stored on the report.
77
+ *
78
+ * Taken over the described MATERIAL, not over the whole `ReportInput`: the
79
+ * report id, the reporter and the allegations are properties of the report, and
80
+ * including them would mean two people reporting identical content produced
81
+ * different hashes — which is the opposite of what this hash is for. Key order
82
+ * is fixed by the literal below rather than by `Object.keys`, so the digest is
83
+ * stable across Node versions and across a refactor that reorders a field.
84
+ */
85
+ function snapshotHash(snapshot) {
86
+ const canonical = JSON.stringify({
87
+ subject: {
88
+ externalId: snapshot.subject.externalId,
89
+ type: snapshot.subject.type,
90
+ author: snapshot.subject.author?.oxyUserId ?? null,
91
+ },
92
+ content: snapshot.content,
93
+ attachments: snapshot.attachments ?? [],
94
+ context: snapshot.context ?? [],
95
+ });
96
+ return `sha256:${(0, crypto_1.createHash)('sha256').update(canonical, 'utf8').digest('hex')}`;
97
+ }
98
+ function createSubjectRegistry(providers) {
99
+ const byType = new Map();
100
+ for (const provider of providers) {
101
+ const existing = byType.get(provider.reportedType);
102
+ if (existing) {
103
+ /**
104
+ * Two providers for one noun is not a merge to resolve quietly: whichever
105
+ * one lost would describe nothing, and the subject type a jury reasons
106
+ * about would depend on array order.
107
+ */
108
+ throw new Error(`Two moderation subject providers are registered for '${provider.reportedType}' ` +
109
+ `('${existing.subjectType}' and '${provider.subjectType}'). A reported type has one provider.`);
110
+ }
111
+ byType.set(provider.reportedType, provider);
112
+ }
113
+ return {
114
+ providerFor: (reportedType) => byType.get(reportedType),
115
+ deliverableTypes: () => Array.from(byType.keys()),
116
+ };
117
+ }
118
+ /**
119
+ * Describe a stored report for delivery, or report why it cannot be described.
120
+ *
121
+ * Returns `null` when the reported object no longer exists. That is not an error
122
+ * either: content deleted between the report and its delivery is ordinary, and
123
+ * evidence stays available through retention on CrowdSource's side — but an
124
+ * object the application never got to snapshot has no evidence to keep.
125
+ */
126
+ async function buildModerationReportInput(input) {
127
+ const { report, registry, taxonomy } = input;
128
+ const provider = registry.providerFor(report.reportedType);
129
+ if (!provider)
130
+ throw new ModerationSubjectUnsupportedError(report.reportedType);
131
+ const snapshot = await provider.snapshot(report.reportedId);
132
+ if (!snapshot)
133
+ return null;
134
+ const allegationCodes = taxonomy.allegationsFor(report.categories);
135
+ if (allegationCodes.length === 0)
136
+ throw new ModerationTaxonomyError(report.categories);
137
+ const details = report.details?.trim();
138
+ return {
139
+ reportInput: {
140
+ externalReportId: report.id,
141
+ subject: snapshot.subject,
142
+ content: snapshot.content,
143
+ ...(snapshot.attachments === undefined ? {} : { attachments: snapshot.attachments }),
144
+ ...(snapshot.context === undefined ? {} : { context: snapshot.context }),
145
+ /**
146
+ * The reporter's own words ride on the FIRST allegation only.
147
+ *
148
+ * Repeating one free-text field across every code would say the reporter
149
+ * wrote it about each of them separately, and details are the reporter's
150
+ * claim and never evidence for it.
151
+ */
152
+ allegations: allegationCodes.map((code, index) => index === 0 && details ? { code, details } : { code }),
153
+ /**
154
+ * The Oxy subject IS the binding proof. Reporters are stored as Oxy user
155
+ * ids, so there is no separate binding step to implement here.
156
+ */
157
+ reportedBy: { oxyUserId: report.reporter },
158
+ /**
159
+ * The moment the USER reported it — the local report's own timestamp, not
160
+ * the moment of delivery. Any value invented per attempt would make every
161
+ * retry from the outbox a permanent 409.
162
+ */
163
+ submittedAt: report.createdAt,
164
+ metadata: {
165
+ /**
166
+ * The application's own entries FIRST, so the two below cannot be
167
+ * shadowed. An adopter that names `taxonomyVersion` or `categories` gets
168
+ * them overwritten rather than winning — a case has to be readable back
169
+ * against the mapping that produced it, and that is not negotiable per
170
+ * application.
171
+ */
172
+ ...taxonomy.metadata,
173
+ /** So a case can be read back against the mapping that produced it. */
174
+ taxonomyVersion: taxonomy.version,
175
+ categories: [...report.categories].sort().join(','),
176
+ },
177
+ },
178
+ snapshotHash: snapshotHash(snapshot),
179
+ };
180
+ }
181
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/outbox/evidence.ts"],"names":[],"mappings":";;;AA2FA,oCAYC;AAuBD,sDAwBC;AAiBD,gEA+DC;AAtOD,mCAAoC;AASpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,iCAAkC,SAAQ,KAAK;IAG1D,YAAY,YAAoB;QAC9B,KAAK,CAAC,qDAAqD,YAAY,IAAI,CAAC,CAAC;QAHtE,cAAS,GAAG,KAAK,CAAC;QAIzB,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;IAClD,CAAC;CACF;AAPD,8EAOC;AAED;;;;;;;;GAQG;AACH,MAAa,uBAAwB,SAAQ,KAAK;IAGhD,YAAY,UAA6B;QACvC,KAAK,CACH,8DAA8D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACtF,sGAAsG,CACzG,CAAC;QANK,cAAS,GAAG,KAAK,CAAC;QAOzB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAVD,0DAUC;AAED;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,QAAmC;IAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC/B,OAAO,EAAE;YACP,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU;YACvC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI;YAC3B,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;SACnD;QACD,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,EAAE;QACvC,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,EAAE;KAChC,CAAC,CAAC;IACH,OAAO,UAAU,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAClF,CAAC;AAuBD,SAAgB,qBAAqB,CACnC,SAA+C;IAE/C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqC,CAAC;IAC5D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,QAAQ,EAAE,CAAC;YACb;;;;eAIG;YACH,MAAM,IAAI,KAAK,CACb,wDAAwD,QAAQ,CAAC,YAAY,IAAI;gBAC/E,KAAK,QAAQ,CAAC,WAAW,UAAU,QAAQ,CAAC,WAAW,uCAAuC,CACjG,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,WAAW,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QACvD,gBAAgB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC;AASD;;;;;;;GAOG;AACI,KAAK,UAAU,0BAA0B,CAAC,KAOhD;IACC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3D,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,iCAAiC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAEhF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,eAAe,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IAEvC,OAAO;QACL,WAAW,EAAE;YACX,gBAAgB,EAAE,MAAM,CAAC,EAAE;YAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,GAAG,CAAC,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC;YACpF,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;YACxE;;;;;;eAMG;YACH,WAAW,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC/C,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CACtD;YACD;;;eAGG;YACH,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE;YAC1C;;;;eAIG;YACH,WAAW,EAAE,MAAM,CAAC,SAAS;YAC7B,QAAQ,EAAE;gBACR;;;;;;mBAMG;gBACH,GAAG,QAAQ,CAAC,QAAQ;gBACpB,uEAAuE;gBACvE,eAAe,EAAE,QAAQ,CAAC,OAAO;gBACjC,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;aACpD;SACF;QACD,YAAY,EAAE,YAAY,CAAC,QAAQ,CAAC;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,78 @@
1
+ import type { ProcessedEventStore } from '../express/index.js';
2
+ import { type OutboxService } from './outbox/service.js';
3
+ import type { ModerationEventStore, ModerationTransactionRunner } from './store/types.js';
4
+ /**
5
+ * What happens between "a signed decision arrived" and "2xx".
6
+ *
7
+ * The receiver's contract is to answer quickly and queue the processing. So
8
+ * exactly two writes happen here, in ONE transaction — the event's audit row is
9
+ * completed and a durable `decision.apply` event is created — and the dispatcher
10
+ * does the rest.
11
+ *
12
+ * The transaction is what makes the dedupe safe. The middleware has already
13
+ * claimed the event id by inserting the row (see {@link createProcessedEventStore});
14
+ * if completing that row and queueing the work were two operations, a crash
15
+ * between them would leave an event that is permanently deduplicated with no
16
+ * work queued — a decision silently lost, with a row that says it arrived.
17
+ * Committing both together means the only two possible outcomes are "recorded
18
+ * and queued" or "neither", and "neither" releases the claim and gets
19
+ * redelivered.
20
+ */
21
+ /**
22
+ * The webhook dedupe store, backed by the moderation event log.
23
+ *
24
+ * `@crowdsource.you/core/express` defaults to an in-process store and says exactly
25
+ * when that is not enough: two instances behind a load balancer each keep their
26
+ * own, so a redelivery landing on the other instance is not deduplicated. Every
27
+ * Oxy backend runs several tasks behind one load balancer, so this is that case.
28
+ *
29
+ * The claim/release contract is the SDK's, and it is the right one. A row
30
+ * inserted BEFORE the handler runs means a concurrent redelivery cannot also run
31
+ * it; deleting that row when the handler THROWS means the sender's retry
32
+ * schedule can still deliver the event later. Recording the id only after
33
+ * success would let two copies run at once; recording it before and never
34
+ * releasing would make a transient failure permanent and lose a decision
35
+ * silently.
36
+ *
37
+ * The retention window is computed HERE rather than in a store, so both backends
38
+ * keep an audit row for the same length of time.
39
+ */
40
+ export declare function createProcessedEventStore<TTx>(events: ModerationEventStore<TTx>): ProcessedEventStore;
41
+ export interface RecordDecisionEventInput {
42
+ eventId: string;
43
+ type: string;
44
+ caseId: string;
45
+ /**
46
+ * The decision as delivered.
47
+ *
48
+ * `unknown`, deliberately. It is stored whole and parsed against the published
49
+ * contract by the worker that acts on it — these payloads are deliberately
50
+ * loose, and validating here would mean an event whose shape this deployment
51
+ * does not recognise yet is refused at the door and retried until it
52
+ * dead-letters, instead of being kept until the code catches up.
53
+ */
54
+ decision: unknown;
55
+ }
56
+ export interface InboundService {
57
+ /** Record a decision-bearing event and queue its application. */
58
+ recordDecisionEvent(input: RecordDecisionEventInput): Promise<void>;
59
+ /**
60
+ * Record an event there is nothing to do about.
61
+ *
62
+ * `case.created`, `case.escalated`, `case.closed` and any type a newer
63
+ * CrowdSource introduces. No outbox row, because no work — but the row is
64
+ * kept, because "did CrowdSource tell us about this case, and when" is the
65
+ * first question asked when a report looks stuck, and it has to be answerable.
66
+ */
67
+ recordIgnoredEvent(input: {
68
+ eventId: string;
69
+ type: string;
70
+ caseId?: string;
71
+ }): Promise<void>;
72
+ }
73
+ export declare function createInboundService<TTx>(input: {
74
+ transaction: ModerationTransactionRunner<TTx>;
75
+ events: ModerationEventStore<TTx>;
76
+ outbox: OutboxService<TTx>;
77
+ }): InboundService;
78
+ //# sourceMappingURL=inbound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../src/outbox/inbound.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAE1F;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAC3C,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC,GAChC,mBAAmB,CAerB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE;;;;;;;OAOG;IACH,kBAAkB,CAAC,KAAK,EAAE;QACxB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE;IAC/C,WAAW,EAAE,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CAC5B,GAAG,cAAc,CAwCjB"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createProcessedEventStore = createProcessedEventStore;
4
+ exports.createInboundService = createInboundService;
5
+ const service_js_1 = require("./outbox/service.js");
6
+ const retention_js_1 = require("./retention.js");
7
+ /**
8
+ * What happens between "a signed decision arrived" and "2xx".
9
+ *
10
+ * The receiver's contract is to answer quickly and queue the processing. So
11
+ * exactly two writes happen here, in ONE transaction — the event's audit row is
12
+ * completed and a durable `decision.apply` event is created — and the dispatcher
13
+ * does the rest.
14
+ *
15
+ * The transaction is what makes the dedupe safe. The middleware has already
16
+ * claimed the event id by inserting the row (see {@link createProcessedEventStore});
17
+ * if completing that row and queueing the work were two operations, a crash
18
+ * between them would leave an event that is permanently deduplicated with no
19
+ * work queued — a decision silently lost, with a row that says it arrived.
20
+ * Committing both together means the only two possible outcomes are "recorded
21
+ * and queued" or "neither", and "neither" releases the claim and gets
22
+ * redelivered.
23
+ */
24
+ /**
25
+ * The webhook dedupe store, backed by the moderation event log.
26
+ *
27
+ * `@crowdsource.you/core/express` defaults to an in-process store and says exactly
28
+ * when that is not enough: two instances behind a load balancer each keep their
29
+ * own, so a redelivery landing on the other instance is not deduplicated. Every
30
+ * Oxy backend runs several tasks behind one load balancer, so this is that case.
31
+ *
32
+ * The claim/release contract is the SDK's, and it is the right one. A row
33
+ * inserted BEFORE the handler runs means a concurrent redelivery cannot also run
34
+ * it; deleting that row when the handler THROWS means the sender's retry
35
+ * schedule can still deliver the event later. Recording the id only after
36
+ * success would let two copies run at once; recording it before and never
37
+ * releasing would make a transient failure permanent and lose a decision
38
+ * silently.
39
+ *
40
+ * The retention window is computed HERE rather than in a store, so both backends
41
+ * keep an audit row for the same length of time.
42
+ */
43
+ function createProcessedEventStore(events) {
44
+ return {
45
+ async claim(eventId) {
46
+ const now = new Date();
47
+ return await events.claim({
48
+ eventId,
49
+ receivedAt: now,
50
+ expiresAt: new Date(now.getTime() + retention_js_1.MODERATION_EVENT_RETENTION_SECONDS * 1000),
51
+ });
52
+ },
53
+ async release(eventId) {
54
+ await events.release(eventId);
55
+ },
56
+ };
57
+ }
58
+ function createInboundService(input) {
59
+ return {
60
+ async recordDecisionEvent(event) {
61
+ await input.transaction.run(async (tx) => {
62
+ const now = new Date();
63
+ await input.events.markQueued({
64
+ eventId: event.eventId,
65
+ type: event.type,
66
+ caseId: event.caseId,
67
+ payload: { caseId: event.caseId, decision: event.decision },
68
+ now,
69
+ }, tx);
70
+ await input.outbox.enqueue({
71
+ eventId: (0, service_js_1.decisionApplyEventId)(event.eventId),
72
+ kind: 'decision.apply',
73
+ payload: {
74
+ eventId: event.eventId,
75
+ caseId: event.caseId,
76
+ decision: event.decision,
77
+ },
78
+ }, tx);
79
+ });
80
+ },
81
+ async recordIgnoredEvent(event) {
82
+ await input.events.markIgnored({
83
+ eventId: event.eventId,
84
+ type: event.type,
85
+ ...(event.caseId === undefined ? {} : { caseId: event.caseId }),
86
+ now: new Date(),
87
+ });
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=inbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../src/outbox/inbound.ts"],"names":[],"mappings":";;AA0CA,8DAiBC;AAoCD,oDA4CC;AA1ID,oDAA+E;AAC/E,iDAAoE;AAGpE;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,yBAAyB,CACvC,MAAiC;IAEjC,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAe;YACzB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC;gBACxB,OAAO;gBACP,UAAU,EAAE,GAAG;gBACf,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,iDAAkC,GAAG,IAAK,CAAC;aAChF,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,OAAe;YAC3B,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC;AAoCD,SAAgB,oBAAoB,CAAM,KAIzC;IACC,OAAO;QACL,KAAK,CAAC,mBAAmB,CAAC,KAAK;YAC7B,MAAM,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,CAC3B;oBACE,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE;oBAC3D,GAAG;iBACJ,EACD,EAAE,CACH,CAAC;gBAEF,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CACxB;oBACE,OAAO,EAAE,IAAA,iCAAoB,EAAC,KAAK,CAAC,OAAO,CAAC;oBAC5C,IAAI,EAAE,gBAAgB;oBACtB,OAAO,EAAE;wBACP,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;qBACzB;iBACF,EACD,EAAE,CACH,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,KAAK;YAC5B,MAAM,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC;gBAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC/D,GAAG,EAAE,IAAI,IAAI,EAAE;aAChB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `@crowdsource.you/core/outbox` — the application half of a CrowdSource integration.
3
+ *
4
+ * An application that adopts CrowdSource has to solve the same six problems
5
+ * every other application does: store a report and its promise of delivery
6
+ * atomically, deliver it with retries and a dead-letter path, receive signed
7
+ * decisions without a body parser destroying the signature, deduplicate
8
+ * redeliveries across several tasks, apply a decision without a stale revision
9
+ * overwriting a fresh one, and carry out consequences exactly once and
10
+ * reversibly. None of that has anything to do with what the application's
11
+ * objects are.
12
+ *
13
+ * So all of it is here, and an application supplies four things: its subjects,
14
+ * its category mapping, its enforcement tables, and a STORE built by the
15
+ * PostgreSQL store factory.
16
+ *
17
+ * ```ts
18
+ * import { createModerationIntegration } from '@crowdsource.you/core/outbox';
19
+ * import { postgresModerationStore } from '@crowdsource.you/core/outbox/postgres';
20
+ *
21
+ * const moderation = createModerationIntegration({
22
+ * store,
23
+ * crowdSource: { enabled: true, serviceKey, webhookSecret, enforcementMode: 'observe' },
24
+ * subjects: [listingSubjectProvider(), reviewSubjectProvider()],
25
+ * taxonomy: { version: '2026.07', allegationsFor },
26
+ * enforcement: commerceEnforcement,
27
+ * logger,
28
+ * });
29
+ *
30
+ * // Indexes before the first write: the unique ones ARE the exactly-once
31
+ * // mechanism, and an index that does not exist yet refuses nothing.
32
+ * await store.ensureSchema();
33
+ *
34
+ * // BEFORE express.json() — the signature covers the bytes that arrived.
35
+ * app.use('/webhooks', moderation.webhookRouter());
36
+ * app.use(express.json());
37
+ *
38
+ * moderation.dispatcher.start();
39
+ * ```
40
+ *
41
+ * Two invariants are ENFORCED here rather than documented, because both fail
42
+ * silently and neither shows up in a test that only asserts the happy path:
43
+ *
44
+ * 1. Nothing can be enqueued that is not already recorded in the outbox, in the
45
+ * same transaction. {@link ModerationOutboxTransactionError} is thrown by the
46
+ * only writer of that collection when the transaction it was handed is not
47
+ * open.
48
+ * 2. The webhook receiver reads raw bytes. Mounted after a JSON parser it
49
+ * refuses rather than verifying a signature over a re-serialisation.
50
+ *
51
+ * Types come from `@crowdsource.you/contracts` and `@crowdsource.you/core`. This
52
+ * package re-exports none of them: a `Decision` or a `TaxonomyCode` has exactly
53
+ * one definition.
54
+ */
55
+ export { createModerationIntegration } from './integration.js';
56
+ export type { ModerationIntegration } from './integration.js';
57
+ /**
58
+ * The retention windows are storage-independent policy, so they stay here while
59
+ * PostgreSQL-specific tables and stores live behind the `/postgres` subpath.
60
+ */
61
+ export { MODERATION_EVENT_RETENTION_SECONDS, MODERATION_OUTBOX_RETENTION_SECONDS, } from './retention.js';
62
+ export { ModerationOutboxTransactionError, decisionApplyEventId, isRetryableDeliveryError, reportSubmitEventId, } from './outbox/service.js';
63
+ export type { ModerationOutboxFailure, ModerationOutboxHandler, OutboxDrain, OutboxService, } from './outbox/service.js';
64
+ export type { ModerationEnforcementInsert, ModerationEnforcementKey, ModerationEnforcementStore, ModerationEventStore, ModerationOutboxStore, ModerationReportDecisionUpdate, ModerationReportInsert, ModerationReportRef, ModerationReportStore, ModerationStore, ModerationTransactionRunner, } from './store/types.js';
65
+ export { ModerationOutboxDispatcher } from './outbox/dispatcher.js';
66
+ export { ModerationReconciliationJob } from './reconciliation.js';
67
+ export type { ReconcileModerationReports } from './reconciliation.js';
68
+ export { DuplicateReportError } from './intake.js';
69
+ export { CrowdSourceUnavailableError, ModerationDeliveryRejectedError, } from './delivery.js';
70
+ export { ModerationDecisionDeferredError, ModerationDecisionRejectedError, } from './decision.js';
71
+ export { ModerationSubjectUnsupportedError, ModerationTaxonomyError, createSubjectRegistry, snapshotHash, } from './evidence.js';
72
+ export type { ModerationReportInput, SubjectRegistry } from './evidence.js';
73
+ export { ModerationRestoreDirectionError, assertRestoreDirection, planEnforcement, primaryAction, } from './enforcement/planner.js';
74
+ export type { EnforcementExecutor } from './enforcement/executor.js';
75
+ export { localStatusForDecision } from './reportStatus.js';
76
+ export { createProcessedEventStore } from './inbound.js';
77
+ export type { InboundService, RecordDecisionEventInput } from './inbound.js';
78
+ export type { CreateReportInput, CreateReportResult, CrowdSourceConnectionConfig, EnforcementEffect, EnforcementOutcome, EnforcementPreviousState, EnforcementSubject, ModerationContextResource, ModerationDispatchResult, ModerationEnforcementConfig, ModerationEnforcementMode, ModerationIntegrationConfig, ModerationLocalStatus, ModerationLogger, ModerationMetrics, ModerationOutboxEvent, ModerationOutboxKind, ModerationOutboxPayload, ModerationOutboxStatus, ModerationReconciliationResult, ModerationReportFields, ModerationResource, ModerationSubjectProvider, ModerationSubjectSnapshot, ModerationTaxonomy, PlannedEnforcementAction, ReportDecisionExtraFields, } from './types.js';
79
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/outbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D;;;GAGG;AACH,OAAO,EACL,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gCAAgC,EAChC,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,uBAAuB,EACvB,uBAAuB,EACvB,WAAW,EACX,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,2BAA2B,EAC3B,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EACL,2BAA2B,EAC3B,+BAA+B,GAChC,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iCAAiC,EACjC,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE5E,OAAO,EACL,+BAA+B,EAC/B,sBAAsB,EACtB,eAAe,EACf,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAE7E,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,2BAA2B,EAC3B,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC3B,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,YAAY,CAAC"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ /**
3
+ * `@crowdsource.you/core/outbox` — the application half of a CrowdSource integration.
4
+ *
5
+ * An application that adopts CrowdSource has to solve the same six problems
6
+ * every other application does: store a report and its promise of delivery
7
+ * atomically, deliver it with retries and a dead-letter path, receive signed
8
+ * decisions without a body parser destroying the signature, deduplicate
9
+ * redeliveries across several tasks, apply a decision without a stale revision
10
+ * overwriting a fresh one, and carry out consequences exactly once and
11
+ * reversibly. None of that has anything to do with what the application's
12
+ * objects are.
13
+ *
14
+ * So all of it is here, and an application supplies four things: its subjects,
15
+ * its category mapping, its enforcement tables, and a STORE built by the
16
+ * PostgreSQL store factory.
17
+ *
18
+ * ```ts
19
+ * import { createModerationIntegration } from '@crowdsource.you/core/outbox';
20
+ * import { postgresModerationStore } from '@crowdsource.you/core/outbox/postgres';
21
+ *
22
+ * const moderation = createModerationIntegration({
23
+ * store,
24
+ * crowdSource: { enabled: true, serviceKey, webhookSecret, enforcementMode: 'observe' },
25
+ * subjects: [listingSubjectProvider(), reviewSubjectProvider()],
26
+ * taxonomy: { version: '2026.07', allegationsFor },
27
+ * enforcement: commerceEnforcement,
28
+ * logger,
29
+ * });
30
+ *
31
+ * // Indexes before the first write: the unique ones ARE the exactly-once
32
+ * // mechanism, and an index that does not exist yet refuses nothing.
33
+ * await store.ensureSchema();
34
+ *
35
+ * // BEFORE express.json() — the signature covers the bytes that arrived.
36
+ * app.use('/webhooks', moderation.webhookRouter());
37
+ * app.use(express.json());
38
+ *
39
+ * moderation.dispatcher.start();
40
+ * ```
41
+ *
42
+ * Two invariants are ENFORCED here rather than documented, because both fail
43
+ * silently and neither shows up in a test that only asserts the happy path:
44
+ *
45
+ * 1. Nothing can be enqueued that is not already recorded in the outbox, in the
46
+ * same transaction. {@link ModerationOutboxTransactionError} is thrown by the
47
+ * only writer of that collection when the transaction it was handed is not
48
+ * open.
49
+ * 2. The webhook receiver reads raw bytes. Mounted after a JSON parser it
50
+ * refuses rather than verifying a signature over a re-serialisation.
51
+ *
52
+ * Types come from `@crowdsource.you/contracts` and `@crowdsource.you/core`. This
53
+ * package re-exports none of them: a `Decision` or a `TaxonomyCode` has exactly
54
+ * one definition.
55
+ */
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ exports.createProcessedEventStore = exports.localStatusForDecision = exports.primaryAction = exports.planEnforcement = exports.assertRestoreDirection = exports.ModerationRestoreDirectionError = exports.snapshotHash = exports.createSubjectRegistry = exports.ModerationTaxonomyError = exports.ModerationSubjectUnsupportedError = exports.ModerationDecisionRejectedError = exports.ModerationDecisionDeferredError = exports.ModerationDeliveryRejectedError = exports.CrowdSourceUnavailableError = exports.DuplicateReportError = exports.ModerationReconciliationJob = exports.ModerationOutboxDispatcher = exports.reportSubmitEventId = exports.isRetryableDeliveryError = exports.decisionApplyEventId = exports.ModerationOutboxTransactionError = exports.MODERATION_OUTBOX_RETENTION_SECONDS = exports.MODERATION_EVENT_RETENTION_SECONDS = exports.createModerationIntegration = void 0;
58
+ var integration_js_1 = require("./integration.js");
59
+ Object.defineProperty(exports, "createModerationIntegration", { enumerable: true, get: function () { return integration_js_1.createModerationIntegration; } });
60
+ /**
61
+ * The retention windows are storage-independent policy, so they stay here while
62
+ * PostgreSQL-specific tables and stores live behind the `/postgres` subpath.
63
+ */
64
+ var retention_js_1 = require("./retention.js");
65
+ Object.defineProperty(exports, "MODERATION_EVENT_RETENTION_SECONDS", { enumerable: true, get: function () { return retention_js_1.MODERATION_EVENT_RETENTION_SECONDS; } });
66
+ Object.defineProperty(exports, "MODERATION_OUTBOX_RETENTION_SECONDS", { enumerable: true, get: function () { return retention_js_1.MODERATION_OUTBOX_RETENTION_SECONDS; } });
67
+ var service_js_1 = require("./outbox/service.js");
68
+ Object.defineProperty(exports, "ModerationOutboxTransactionError", { enumerable: true, get: function () { return service_js_1.ModerationOutboxTransactionError; } });
69
+ Object.defineProperty(exports, "decisionApplyEventId", { enumerable: true, get: function () { return service_js_1.decisionApplyEventId; } });
70
+ Object.defineProperty(exports, "isRetryableDeliveryError", { enumerable: true, get: function () { return service_js_1.isRetryableDeliveryError; } });
71
+ Object.defineProperty(exports, "reportSubmitEventId", { enumerable: true, get: function () { return service_js_1.reportSubmitEventId; } });
72
+ var dispatcher_js_1 = require("./outbox/dispatcher.js");
73
+ Object.defineProperty(exports, "ModerationOutboxDispatcher", { enumerable: true, get: function () { return dispatcher_js_1.ModerationOutboxDispatcher; } });
74
+ var reconciliation_js_1 = require("./reconciliation.js");
75
+ Object.defineProperty(exports, "ModerationReconciliationJob", { enumerable: true, get: function () { return reconciliation_js_1.ModerationReconciliationJob; } });
76
+ var intake_js_1 = require("./intake.js");
77
+ Object.defineProperty(exports, "DuplicateReportError", { enumerable: true, get: function () { return intake_js_1.DuplicateReportError; } });
78
+ var delivery_js_1 = require("./delivery.js");
79
+ Object.defineProperty(exports, "CrowdSourceUnavailableError", { enumerable: true, get: function () { return delivery_js_1.CrowdSourceUnavailableError; } });
80
+ Object.defineProperty(exports, "ModerationDeliveryRejectedError", { enumerable: true, get: function () { return delivery_js_1.ModerationDeliveryRejectedError; } });
81
+ var decision_js_1 = require("./decision.js");
82
+ Object.defineProperty(exports, "ModerationDecisionDeferredError", { enumerable: true, get: function () { return decision_js_1.ModerationDecisionDeferredError; } });
83
+ Object.defineProperty(exports, "ModerationDecisionRejectedError", { enumerable: true, get: function () { return decision_js_1.ModerationDecisionRejectedError; } });
84
+ var evidence_js_1 = require("./evidence.js");
85
+ Object.defineProperty(exports, "ModerationSubjectUnsupportedError", { enumerable: true, get: function () { return evidence_js_1.ModerationSubjectUnsupportedError; } });
86
+ Object.defineProperty(exports, "ModerationTaxonomyError", { enumerable: true, get: function () { return evidence_js_1.ModerationTaxonomyError; } });
87
+ Object.defineProperty(exports, "createSubjectRegistry", { enumerable: true, get: function () { return evidence_js_1.createSubjectRegistry; } });
88
+ Object.defineProperty(exports, "snapshotHash", { enumerable: true, get: function () { return evidence_js_1.snapshotHash; } });
89
+ var planner_js_1 = require("./enforcement/planner.js");
90
+ Object.defineProperty(exports, "ModerationRestoreDirectionError", { enumerable: true, get: function () { return planner_js_1.ModerationRestoreDirectionError; } });
91
+ Object.defineProperty(exports, "assertRestoreDirection", { enumerable: true, get: function () { return planner_js_1.assertRestoreDirection; } });
92
+ Object.defineProperty(exports, "planEnforcement", { enumerable: true, get: function () { return planner_js_1.planEnforcement; } });
93
+ Object.defineProperty(exports, "primaryAction", { enumerable: true, get: function () { return planner_js_1.primaryAction; } });
94
+ var reportStatus_js_1 = require("./reportStatus.js");
95
+ Object.defineProperty(exports, "localStatusForDecision", { enumerable: true, get: function () { return reportStatus_js_1.localStatusForDecision; } });
96
+ var inbound_js_1 = require("./inbound.js");
97
+ Object.defineProperty(exports, "createProcessedEventStore", { enumerable: true, get: function () { return inbound_js_1.createProcessedEventStore; } });
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/outbox/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;;;AAEH,mDAA+D;AAAtD,6HAAA,2BAA2B,OAAA;AAGpC;;;GAGG;AACH,+CAGwB;AAFtB,kIAAA,kCAAkC,OAAA;AAClC,mIAAA,mCAAmC,OAAA;AAGrC,kDAK6B;AAJ3B,8HAAA,gCAAgC,OAAA;AAChC,kHAAA,oBAAoB,OAAA;AACpB,sHAAA,wBAAwB,OAAA;AACxB,iHAAA,mBAAmB,OAAA;AAuBrB,wDAAoE;AAA3D,2HAAA,0BAA0B,OAAA;AACnC,yDAAkE;AAAzD,gIAAA,2BAA2B,OAAA;AAGpC,yCAAmD;AAA1C,iHAAA,oBAAoB,OAAA;AAE7B,6CAGuB;AAFrB,0HAAA,2BAA2B,OAAA;AAC3B,8HAAA,+BAA+B,OAAA;AAGjC,6CAGuB;AAFrB,8HAAA,+BAA+B,OAAA;AAC/B,8HAAA,+BAA+B,OAAA;AAGjC,6CAKuB;AAJrB,gIAAA,iCAAiC,OAAA;AACjC,sHAAA,uBAAuB,OAAA;AACvB,oHAAA,qBAAqB,OAAA;AACrB,2GAAA,YAAY,OAAA;AAId,uDAKkC;AAJhC,6HAAA,+BAA+B,OAAA;AAC/B,oHAAA,sBAAsB,OAAA;AACtB,6GAAA,eAAe,OAAA;AACf,2GAAA,aAAa,OAAA;AAIf,qDAA2D;AAAlD,yHAAA,sBAAsB,OAAA;AAE/B,2CAAyD;AAAhD,uHAAA,yBAAyB,OAAA"}
@@ -0,0 +1,62 @@
1
+ import type { SubjectRegistry } from './evidence.js';
2
+ import { type OutboxService } from './outbox/service.js';
3
+ import type { ModerationReportStore, ModerationTransactionRunner } from './store/types.js';
4
+ import type { CreateReportInput, CreateReportResult, ModerationReportFields } from './types.js';
5
+ /**
6
+ * Storing a report and, when there is somewhere to send it, the promise to
7
+ * deliver it — in one operation.
8
+ *
9
+ * This is the only thing in the integration that a user waits for. A 201 from an
10
+ * application's report route means the report row and its outbox event committed
11
+ * together. It does NOT mean CrowdSource accepted anything — CrowdSource may be
12
+ * unreachable, mid-deploy or not yet configured, and the reporter is told their
13
+ * report was received either way, because it was.
14
+ *
15
+ * The transaction is the whole mechanism. Two writes outside one would give two
16
+ * failure modes that are both silent: a report with no delivery event (the
17
+ * report exists, nothing will ever send it, and nobody finds out until somebody
18
+ * asks why a case never opened) or a delivery event with no report (a delivery
19
+ * worker looking up an id that was rolled back). Neither surfaces as an error at
20
+ * the moment it happens, which is exactly why this has to be atomic rather than
21
+ * carefully ordered.
22
+ *
23
+ * The one report with NO delivery event is the one whose type has no subject
24
+ * provider, and that is a different claim entirely: not "delivery failed" but
25
+ * "there was never a route out of this application for this kind of object".
26
+ * Those two must not be conflated, which is why they are different `localStatus`
27
+ * values and why the absent route is written down as a reason rather than
28
+ * inferred from a missing row.
29
+ */
30
+ export declare class DuplicateReportError<TReport> extends Error {
31
+ readonly existing: TReport;
32
+ constructor(existing: TReport);
33
+ }
34
+ /**
35
+ * Store the report, and queue its delivery in the same transaction.
36
+ *
37
+ * Delivery is queued when — and only when — the reported type has a subject
38
+ * provider. A type without one is stored at `received` with the reason recorded,
39
+ * which is the behaviour the application had before CrowdSource existed: the
40
+ * report is a receipt and a local record, and nothing else ever happens to it.
41
+ *
42
+ * That branch is the reason the two writes stay in one transaction rather than
43
+ * being ordered carefully. The condition is read BEFORE the transaction body
44
+ * decides anything, so `localStatus` and the presence of an outbox row are
45
+ * decided together from one fact — a report can never commit as `queued` with
46
+ * nothing to deliver it, nor as `received` with a delivery event that will try
47
+ * anyway.
48
+ *
49
+ * Intake deliberately does not read whether the integration is enabled. A report
50
+ * taken while it is off still gets its delivery event, so turning the flag on
51
+ * delivers the backlog instead of stranding it — the dispatcher is what is
52
+ * gated, not the durable record. Nothing here is conditional on a third party's
53
+ * state; only on whether this application knows how to describe the object at
54
+ * all.
55
+ */
56
+ export declare function createIntake<TReport extends ModerationReportFields, TTx>(input: {
57
+ transaction: ModerationTransactionRunner<TTx>;
58
+ reports: ModerationReportStore<TReport, TTx>;
59
+ registry: SubjectRegistry;
60
+ outbox: OutboxService<TTx>;
61
+ }): (report: CreateReportInput) => Promise<CreateReportResult<TReport>>;
62
+ //# sourceMappingURL=intake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../src/outbox/intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,EACV,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,qBAAa,oBAAoB,CAAC,OAAO,CAAE,SAAQ,KAAK;IACtD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;gBAEf,QAAQ,EAAE,OAAO;CAK9B;AAqDD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,OAAO,SAAS,sBAAsB,EAAE,GAAG,EAAE,KAAK,EAAE;IAC/E,WAAW,EAAE,2BAA2B,CAAC,GAAG,CAAC,CAAC;IAC9C,OAAO,EAAE,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7C,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CAC5B,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAgDtE"}