@ixo/decision-oracle 0.0.0-stage → 0.2.1

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 (1118) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +794 -2
  3. package/dist/act.d.ts +87 -0
  4. package/dist/act.d.ts.map +1 -0
  5. package/dist/act.js +20 -0
  6. package/dist/act.js.map +1 -0
  7. package/dist/app.d.ts +22 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +128 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/c2pa.wasm +0 -0
  12. package/dist/cli/commands/api.d.ts +50 -0
  13. package/dist/cli/commands/api.d.ts.map +1 -0
  14. package/dist/cli/commands/api.js +737 -0
  15. package/dist/cli/commands/api.js.map +1 -0
  16. package/dist/cli/commands/create-collection.d.ts +40 -0
  17. package/dist/cli/commands/create-collection.d.ts.map +1 -0
  18. package/dist/cli/commands/create-collection.js +318 -0
  19. package/dist/cli/commands/create-collection.js.map +1 -0
  20. package/dist/cli/commands/create-deed.d.ts +31 -0
  21. package/dist/cli/commands/create-deed.d.ts.map +1 -0
  22. package/dist/cli/commands/create-deed.js +208 -0
  23. package/dist/cli/commands/create-deed.js.map +1 -0
  24. package/dist/cli/commands/delegation.d.ts +26 -0
  25. package/dist/cli/commands/delegation.d.ts.map +1 -0
  26. package/dist/cli/commands/delegation.js +162 -0
  27. package/dist/cli/commands/delegation.js.map +1 -0
  28. package/dist/cli/commands/derive.d.ts +22 -0
  29. package/dist/cli/commands/derive.d.ts.map +1 -0
  30. package/dist/cli/commands/derive.js +53 -0
  31. package/dist/cli/commands/derive.js.map +1 -0
  32. package/dist/cli/commands/engine.d.ts +25 -0
  33. package/dist/cli/commands/engine.d.ts.map +1 -0
  34. package/dist/cli/commands/engine.js +107 -0
  35. package/dist/cli/commands/engine.js.map +1 -0
  36. package/dist/cli/commands/erase.d.ts +17 -0
  37. package/dist/cli/commands/erase.d.ts.map +1 -0
  38. package/dist/cli/commands/erase.js +117 -0
  39. package/dist/cli/commands/erase.js.map +1 -0
  40. package/dist/cli/commands/facts-run.d.ts +30 -0
  41. package/dist/cli/commands/facts-run.d.ts.map +1 -0
  42. package/dist/cli/commands/facts-run.js +409 -0
  43. package/dist/cli/commands/facts-run.js.map +1 -0
  44. package/dist/cli/commands/facts-scaffold.d.ts +22 -0
  45. package/dist/cli/commands/facts-scaffold.d.ts.map +1 -0
  46. package/dist/cli/commands/facts-scaffold.js +208 -0
  47. package/dist/cli/commands/facts-scaffold.js.map +1 -0
  48. package/dist/cli/commands/init.d.ts +18 -0
  49. package/dist/cli/commands/init.d.ts.map +1 -0
  50. package/dist/cli/commands/init.js +34 -0
  51. package/dist/cli/commands/init.js.map +1 -0
  52. package/dist/cli/commands/login.d.ts +9 -0
  53. package/dist/cli/commands/login.d.ts.map +1 -0
  54. package/dist/cli/commands/login.js +16 -0
  55. package/dist/cli/commands/login.js.map +1 -0
  56. package/dist/cli/commands/logout.d.ts +10 -0
  57. package/dist/cli/commands/logout.d.ts.map +1 -0
  58. package/dist/cli/commands/logout.js +28 -0
  59. package/dist/cli/commands/logout.js.map +1 -0
  60. package/dist/cli/commands/manifest.d.ts +12 -0
  61. package/dist/cli/commands/manifest.d.ts.map +1 -0
  62. package/dist/cli/commands/manifest.js +48 -0
  63. package/dist/cli/commands/manifest.js.map +1 -0
  64. package/dist/cli/commands/oracle-init.d.ts +48 -0
  65. package/dist/cli/commands/oracle-init.d.ts.map +1 -0
  66. package/dist/cli/commands/oracle-init.js +1122 -0
  67. package/dist/cli/commands/oracle-init.js.map +1 -0
  68. package/dist/cli/commands/org.d.ts +28 -0
  69. package/dist/cli/commands/org.d.ts.map +1 -0
  70. package/dist/cli/commands/org.js +309 -0
  71. package/dist/cli/commands/org.js.map +1 -0
  72. package/dist/cli/commands/protocol-review.d.ts +20 -0
  73. package/dist/cli/commands/protocol-review.d.ts.map +1 -0
  74. package/dist/cli/commands/protocol-review.js +162 -0
  75. package/dist/cli/commands/protocol-review.js.map +1 -0
  76. package/dist/cli/commands/publish-protocol.d.ts +43 -0
  77. package/dist/cli/commands/publish-protocol.d.ts.map +1 -0
  78. package/dist/cli/commands/publish-protocol.js +345 -0
  79. package/dist/cli/commands/publish-protocol.js.map +1 -0
  80. package/dist/cli/commands/register.d.ts +16 -0
  81. package/dist/cli/commands/register.d.ts.map +1 -0
  82. package/dist/cli/commands/register.js +54 -0
  83. package/dist/cli/commands/register.js.map +1 -0
  84. package/dist/cli/commands/relink.d.ts +11 -0
  85. package/dist/cli/commands/relink.d.ts.map +1 -0
  86. package/dist/cli/commands/relink.js +36 -0
  87. package/dist/cli/commands/relink.js.map +1 -0
  88. package/dist/cli/commands/rubric-fetch-form.d.ts +16 -0
  89. package/dist/cli/commands/rubric-fetch-form.d.ts.map +1 -0
  90. package/dist/cli/commands/rubric-fetch-form.js +83 -0
  91. package/dist/cli/commands/rubric-fetch-form.js.map +1 -0
  92. package/dist/cli/commands/rubric-validate.d.ts +72 -0
  93. package/dist/cli/commands/rubric-validate.d.ts.map +1 -0
  94. package/dist/cli/commands/rubric-validate.js +163 -0
  95. package/dist/cli/commands/rubric-validate.js.map +1 -0
  96. package/dist/cli/commands/scan.d.ts +13 -0
  97. package/dist/cli/commands/scan.d.ts.map +1 -0
  98. package/dist/cli/commands/scan.js +39 -0
  99. package/dist/cli/commands/scan.js.map +1 -0
  100. package/dist/cli/commands/skills.d.ts +11 -0
  101. package/dist/cli/commands/skills.d.ts.map +1 -0
  102. package/dist/cli/commands/skills.js +19 -0
  103. package/dist/cli/commands/skills.js.map +1 -0
  104. package/dist/cli/commands/submit-claim.d.ts +25 -0
  105. package/dist/cli/commands/submit-claim.d.ts.map +1 -0
  106. package/dist/cli/commands/submit-claim.js +155 -0
  107. package/dist/cli/commands/submit-claim.js.map +1 -0
  108. package/dist/cli/index.d.ts +15 -0
  109. package/dist/cli/index.d.ts.map +1 -0
  110. package/dist/cli/index.js +206 -0
  111. package/dist/cli/index.js.map +1 -0
  112. package/dist/cli/lib/agent-card-schema.d.ts +8 -0
  113. package/dist/cli/lib/agent-card-schema.d.ts.map +1 -0
  114. package/dist/cli/lib/agent-card-schema.js +169 -0
  115. package/dist/cli/lib/agent-card-schema.js.map +1 -0
  116. package/dist/cli/lib/ai-rest.d.ts +12 -0
  117. package/dist/cli/lib/ai-rest.d.ts.map +1 -0
  118. package/dist/cli/lib/ai-rest.js +36 -0
  119. package/dist/cli/lib/ai-rest.js.map +1 -0
  120. package/dist/cli/lib/args.d.ts +33 -0
  121. package/dist/cli/lib/args.d.ts.map +1 -0
  122. package/dist/cli/lib/args.js +24 -0
  123. package/dist/cli/lib/args.js.map +1 -0
  124. package/dist/cli/lib/authhub.d.ts +7 -0
  125. package/dist/cli/lib/authhub.d.ts.map +1 -0
  126. package/dist/cli/lib/authhub.js +210 -0
  127. package/dist/cli/lib/authhub.js.map +1 -0
  128. package/dist/cli/lib/chain.d.ts +264 -0
  129. package/dist/cli/lib/chain.d.ts.map +1 -0
  130. package/dist/cli/lib/chain.js +584 -0
  131. package/dist/cli/lib/chain.js.map +1 -0
  132. package/dist/cli/lib/devvars.d.ts +59 -0
  133. package/dist/cli/lib/devvars.d.ts.map +1 -0
  134. package/dist/cli/lib/devvars.js +206 -0
  135. package/dist/cli/lib/devvars.js.map +1 -0
  136. package/dist/cli/lib/engine.d.ts +54 -0
  137. package/dist/cli/lib/engine.d.ts.map +1 -0
  138. package/dist/cli/lib/engine.js +112 -0
  139. package/dist/cli/lib/engine.js.map +1 -0
  140. package/dist/cli/lib/identity-cards.d.ts +188 -0
  141. package/dist/cli/lib/identity-cards.d.ts.map +1 -0
  142. package/dist/cli/lib/identity-cards.js +261 -0
  143. package/dist/cli/lib/identity-cards.js.map +1 -0
  144. package/dist/cli/lib/matrix-account.d.ts +79 -0
  145. package/dist/cli/lib/matrix-account.d.ts.map +1 -0
  146. package/dist/cli/lib/matrix-account.js +228 -0
  147. package/dist/cli/lib/matrix-account.js.map +1 -0
  148. package/dist/cli/lib/oracle-account.d.ts +108 -0
  149. package/dist/cli/lib/oracle-account.d.ts.map +1 -0
  150. package/dist/cli/lib/oracle-account.js +207 -0
  151. package/dist/cli/lib/oracle-account.js.map +1 -0
  152. package/dist/cli/lib/project.d.ts +22 -0
  153. package/dist/cli/lib/project.d.ts.map +1 -0
  154. package/dist/cli/lib/project.js +62 -0
  155. package/dist/cli/lib/project.js.map +1 -0
  156. package/dist/cli/lib/session.d.ts +109 -0
  157. package/dist/cli/lib/session.d.ts.map +1 -0
  158. package/dist/cli/lib/session.js +354 -0
  159. package/dist/cli/lib/session.js.map +1 -0
  160. package/dist/cli/lib/workorder.d.ts +57 -0
  161. package/dist/cli/lib/workorder.d.ts.map +1 -0
  162. package/dist/cli/lib/workorder.js +101 -0
  163. package/dist/cli/lib/workorder.js.map +1 -0
  164. package/dist/config.d.ts +221 -0
  165. package/dist/config.d.ts.map +1 -0
  166. package/dist/config.js +431 -0
  167. package/dist/config.js.map +1 -0
  168. package/dist/context.d.ts +88 -0
  169. package/dist/context.d.ts.map +1 -0
  170. package/dist/context.js +9 -0
  171. package/dist/context.js.map +1 -0
  172. package/dist/contracts/api.d.ts +3367 -0
  173. package/dist/contracts/api.d.ts.map +1 -0
  174. package/dist/contracts/api.js +1303 -0
  175. package/dist/contracts/api.js.map +1 -0
  176. package/dist/contracts/capabilities.d.ts +126 -0
  177. package/dist/contracts/capabilities.d.ts.map +1 -0
  178. package/dist/contracts/capabilities.js +164 -0
  179. package/dist/contracts/capabilities.js.map +1 -0
  180. package/dist/contracts/claim-source.d.ts +98 -0
  181. package/dist/contracts/claim-source.d.ts.map +1 -0
  182. package/dist/contracts/claim-source.js +17 -0
  183. package/dist/contracts/claim-source.js.map +1 -0
  184. package/dist/contracts/errors.d.ts +150 -0
  185. package/dist/contracts/errors.d.ts.map +1 -0
  186. package/dist/contracts/errors.js +121 -0
  187. package/dist/contracts/errors.js.map +1 -0
  188. package/dist/contracts/index.d.ts +15 -0
  189. package/dist/contracts/index.d.ts.map +1 -0
  190. package/dist/contracts/index.js +11 -0
  191. package/dist/contracts/index.js.map +1 -0
  192. package/dist/contracts/payment-gate.d.ts +129 -0
  193. package/dist/contracts/payment-gate.d.ts.map +1 -0
  194. package/dist/contracts/payment-gate.js +24 -0
  195. package/dist/contracts/payment-gate.js.map +1 -0
  196. package/dist/contracts/start-api-claim.d.ts +90 -0
  197. package/dist/contracts/start-api-claim.d.ts.map +1 -0
  198. package/dist/contracts/start-api-claim.js +22 -0
  199. package/dist/contracts/start-api-claim.js.map +1 -0
  200. package/dist/contracts/webhooks.d.ts +1487 -0
  201. package/dist/contracts/webhooks.d.ts.map +1 -0
  202. package/dist/contracts/webhooks.js +71 -0
  203. package/dist/contracts/webhooks.js.map +1 -0
  204. package/dist/contracts/work-order.d.ts +29 -0
  205. package/dist/contracts/work-order.d.ts.map +1 -0
  206. package/dist/contracts/work-order.js +12 -0
  207. package/dist/contracts/work-order.js.map +1 -0
  208. package/dist/cron/ai-cost.d.ts +29 -0
  209. package/dist/cron/ai-cost.d.ts.map +1 -0
  210. package/dist/cron/ai-cost.js +80 -0
  211. package/dist/cron/ai-cost.js.map +1 -0
  212. package/dist/cron/api-lane.d.ts +39 -0
  213. package/dist/cron/api-lane.d.ts.map +1 -0
  214. package/dist/cron/api-lane.js +203 -0
  215. package/dist/cron/api-lane.js.map +1 -0
  216. package/dist/cron/backlog.d.ts +50 -0
  217. package/dist/cron/backlog.d.ts.map +1 -0
  218. package/dist/cron/backlog.js +115 -0
  219. package/dist/cron/backlog.js.map +1 -0
  220. package/dist/cron/billing.d.ts +11 -0
  221. package/dist/cron/billing.d.ts.map +1 -0
  222. package/dist/cron/billing.js +69 -0
  223. package/dist/cron/billing.js.map +1 -0
  224. package/dist/cron/collection.d.ts +50 -0
  225. package/dist/cron/collection.d.ts.map +1 -0
  226. package/dist/cron/collection.js +118 -0
  227. package/dist/cron/collection.js.map +1 -0
  228. package/dist/cron/funding.d.ts +16 -0
  229. package/dist/cron/funding.d.ts.map +1 -0
  230. package/dist/cron/funding.js +262 -0
  231. package/dist/cron/funding.js.map +1 -0
  232. package/dist/cron/payer-billing.d.ts +38 -0
  233. package/dist/cron/payer-billing.d.ts.map +1 -0
  234. package/dist/cron/payer-billing.js +119 -0
  235. package/dist/cron/payer-billing.js.map +1 -0
  236. package/dist/cron/scan.d.ts +43 -0
  237. package/dist/cron/scan.d.ts.map +1 -0
  238. package/dist/cron/scan.js +250 -0
  239. package/dist/cron/scan.js.map +1 -0
  240. package/dist/db/client.d.ts +14 -0
  241. package/dist/db/client.d.ts.map +1 -0
  242. package/dist/db/client.js +14 -0
  243. package/dist/db/client.js.map +1 -0
  244. package/dist/db/index.d.ts +7 -0
  245. package/dist/db/index.d.ts.map +1 -0
  246. package/dist/db/index.js +7 -0
  247. package/dist/db/index.js.map +1 -0
  248. package/dist/db/schema.d.ts +6738 -0
  249. package/dist/db/schema.d.ts.map +1 -0
  250. package/dist/db/schema.js +1433 -0
  251. package/dist/db/schema.js.map +1 -0
  252. package/dist/define-oracle.d.ts +32 -0
  253. package/dist/define-oracle.d.ts.map +1 -0
  254. package/dist/define-oracle.js +80 -0
  255. package/dist/define-oracle.js.map +1 -0
  256. package/dist/dev-oracle.d.ts +9 -0
  257. package/dist/dev-oracle.d.ts.map +1 -0
  258. package/dist/dev-oracle.js +19 -0
  259. package/dist/dev-oracle.js.map +1 -0
  260. package/dist/dev-worker.d.ts +10 -0
  261. package/dist/dev-worker.d.ts.map +1 -0
  262. package/dist/dev-worker.js +12 -0
  263. package/dist/dev-worker.js.map +1 -0
  264. package/dist/env.d.ts +146 -0
  265. package/dist/env.d.ts.map +1 -0
  266. package/dist/env.js +10 -0
  267. package/dist/env.js.map +1 -0
  268. package/dist/facts/exif.d.ts +43 -0
  269. package/dist/facts/exif.d.ts.map +1 -0
  270. package/dist/facts/exif.js +224 -0
  271. package/dist/facts/exif.js.map +1 -0
  272. package/dist/facts/fact.d.ts +62 -0
  273. package/dist/facts/fact.d.ts.map +1 -0
  274. package/dist/facts/fact.js +105 -0
  275. package/dist/facts/fact.js.map +1 -0
  276. package/dist/facts/geo.d.ts +55 -0
  277. package/dist/facts/geo.d.ts.map +1 -0
  278. package/dist/facts/geo.js +267 -0
  279. package/dist/facts/geo.js.map +1 -0
  280. package/dist/facts/index.d.ts +31 -0
  281. package/dist/facts/index.d.ts.map +1 -0
  282. package/dist/facts/index.js +27 -0
  283. package/dist/facts/index.js.map +1 -0
  284. package/dist/facts/linked-doc.d.ts +60 -0
  285. package/dist/facts/linked-doc.d.ts.map +1 -0
  286. package/dist/facts/linked-doc.js +101 -0
  287. package/dist/facts/linked-doc.js.map +1 -0
  288. package/dist/facts/types.d.ts +278 -0
  289. package/dist/facts/types.d.ts.map +1 -0
  290. package/dist/facts/types.js +19 -0
  291. package/dist/facts/types.js.map +1 -0
  292. package/dist/index.d.ts +25 -0
  293. package/dist/index.d.ts.map +1 -0
  294. package/dist/index.js +19 -0
  295. package/dist/index.js.map +1 -0
  296. package/dist/lib/api-lane/accept.d.ts +29 -0
  297. package/dist/lib/api-lane/accept.d.ts.map +1 -0
  298. package/dist/lib/api-lane/accept.js +218 -0
  299. package/dist/lib/api-lane/accept.js.map +1 -0
  300. package/dist/lib/api-lane/claim-list.d.ts +44 -0
  301. package/dist/lib/api-lane/claim-list.d.ts.map +1 -0
  302. package/dist/lib/api-lane/claim-list.js +92 -0
  303. package/dist/lib/api-lane/claim-list.js.map +1 -0
  304. package/dist/lib/api-lane/company.d.ts +56 -0
  305. package/dist/lib/api-lane/company.d.ts.map +1 -0
  306. package/dist/lib/api-lane/company.js +103 -0
  307. package/dist/lib/api-lane/company.js.map +1 -0
  308. package/dist/lib/api-lane/events.d.ts +21 -0
  309. package/dist/lib/api-lane/events.d.ts.map +1 -0
  310. package/dist/lib/api-lane/events.js +111 -0
  311. package/dist/lib/api-lane/events.js.map +1 -0
  312. package/dist/lib/api-lane/ids.d.ts +39 -0
  313. package/dist/lib/api-lane/ids.d.ts.map +1 -0
  314. package/dist/lib/api-lane/ids.js +78 -0
  315. package/dist/lib/api-lane/ids.js.map +1 -0
  316. package/dist/lib/api-lane/index.d.ts +16 -0
  317. package/dist/lib/api-lane/index.d.ts.map +1 -0
  318. package/dist/lib/api-lane/index.js +16 -0
  319. package/dist/lib/api-lane/index.js.map +1 -0
  320. package/dist/lib/api-lane/linked.d.ts +264 -0
  321. package/dist/lib/api-lane/linked.d.ts.map +1 -0
  322. package/dist/lib/api-lane/linked.js +272 -0
  323. package/dist/lib/api-lane/linked.js.map +1 -0
  324. package/dist/lib/api-lane/media-type.d.ts +15 -0
  325. package/dist/lib/api-lane/media-type.d.ts.map +1 -0
  326. package/dist/lib/api-lane/media-type.js +73 -0
  327. package/dist/lib/api-lane/media-type.js.map +1 -0
  328. package/dist/lib/api-lane/member-emails.d.ts +83 -0
  329. package/dist/lib/api-lane/member-emails.d.ts.map +1 -0
  330. package/dist/lib/api-lane/member-emails.js +213 -0
  331. package/dist/lib/api-lane/member-emails.js.map +1 -0
  332. package/dist/lib/api-lane/members.d.ts +42 -0
  333. package/dist/lib/api-lane/members.d.ts.map +1 -0
  334. package/dist/lib/api-lane/members.js +75 -0
  335. package/dist/lib/api-lane/members.js.map +1 -0
  336. package/dist/lib/api-lane/notify.d.ts +47 -0
  337. package/dist/lib/api-lane/notify.d.ts.map +1 -0
  338. package/dist/lib/api-lane/notify.js +240 -0
  339. package/dist/lib/api-lane/notify.js.map +1 -0
  340. package/dist/lib/api-lane/pause.d.ts +41 -0
  341. package/dist/lib/api-lane/pause.d.ts.map +1 -0
  342. package/dist/lib/api-lane/pause.js +155 -0
  343. package/dist/lib/api-lane/pause.js.map +1 -0
  344. package/dist/lib/api-lane/record.d.ts +76 -0
  345. package/dist/lib/api-lane/record.d.ts.map +1 -0
  346. package/dist/lib/api-lane/record.js +337 -0
  347. package/dist/lib/api-lane/record.js.map +1 -0
  348. package/dist/lib/api-lane/retention.d.ts +43 -0
  349. package/dist/lib/api-lane/retention.d.ts.map +1 -0
  350. package/dist/lib/api-lane/retention.js +176 -0
  351. package/dist/lib/api-lane/retention.js.map +1 -0
  352. package/dist/lib/api-lane/review.d.ts +76 -0
  353. package/dist/lib/api-lane/review.d.ts.map +1 -0
  354. package/dist/lib/api-lane/review.js +355 -0
  355. package/dist/lib/api-lane/review.js.map +1 -0
  356. package/dist/lib/api-lane/reviewers.d.ts +109 -0
  357. package/dist/lib/api-lane/reviewers.d.ts.map +1 -0
  358. package/dist/lib/api-lane/reviewers.js +755 -0
  359. package/dist/lib/api-lane/reviewers.js.map +1 -0
  360. package/dist/lib/api-lane/source-delete.d.ts +16 -0
  361. package/dist/lib/api-lane/source-delete.d.ts.map +1 -0
  362. package/dist/lib/api-lane/source-delete.js +50 -0
  363. package/dist/lib/api-lane/source-delete.js.map +1 -0
  364. package/dist/lib/api-lane/source.d.ts +19 -0
  365. package/dist/lib/api-lane/source.d.ts.map +1 -0
  366. package/dist/lib/api-lane/source.js +226 -0
  367. package/dist/lib/api-lane/source.js.map +1 -0
  368. package/dist/lib/api-lane/submitter.d.ts +22 -0
  369. package/dist/lib/api-lane/submitter.d.ts.map +1 -0
  370. package/dist/lib/api-lane/submitter.js +34 -0
  371. package/dist/lib/api-lane/submitter.js.map +1 -0
  372. package/dist/lib/api-lane/timeline.d.ts +20 -0
  373. package/dist/lib/api-lane/timeline.d.ts.map +1 -0
  374. package/dist/lib/api-lane/timeline.js +23 -0
  375. package/dist/lib/api-lane/timeline.js.map +1 -0
  376. package/dist/lib/api-lane/webhook-crypto.d.ts +44 -0
  377. package/dist/lib/api-lane/webhook-crypto.d.ts.map +1 -0
  378. package/dist/lib/api-lane/webhook-crypto.js +103 -0
  379. package/dist/lib/api-lane/webhook-crypto.js.map +1 -0
  380. package/dist/lib/api-lane/webhooks.d.ts +117 -0
  381. package/dist/lib/api-lane/webhooks.d.ts.map +1 -0
  382. package/dist/lib/api-lane/webhooks.js +503 -0
  383. package/dist/lib/api-lane/webhooks.js.map +1 -0
  384. package/dist/lib/archive.d.ts +64 -0
  385. package/dist/lib/archive.d.ts.map +1 -0
  386. package/dist/lib/archive.js +305 -0
  387. package/dist/lib/archive.js.map +1 -0
  388. package/dist/lib/bech32.d.ts +8 -0
  389. package/dist/lib/bech32.d.ts.map +1 -0
  390. package/dist/lib/bech32.js +39 -0
  391. package/dist/lib/bech32.js.map +1 -0
  392. package/dist/lib/claim-erase.d.ts +22 -0
  393. package/dist/lib/claim-erase.d.ts.map +1 -0
  394. package/dist/lib/claim-erase.js +44 -0
  395. package/dist/lib/claim-erase.js.map +1 -0
  396. package/dist/lib/cursor.d.ts +11 -0
  397. package/dist/lib/cursor.d.ts.map +1 -0
  398. package/dist/lib/cursor.js +20 -0
  399. package/dist/lib/cursor.js.map +1 -0
  400. package/dist/lib/email/send.d.ts +43 -0
  401. package/dist/lib/email/send.d.ts.map +1 -0
  402. package/dist/lib/email/send.js +71 -0
  403. package/dist/lib/email/send.js.map +1 -0
  404. package/dist/lib/email/template.d.ts +217 -0
  405. package/dist/lib/email/template.d.ts.map +1 -0
  406. package/dist/lib/email/template.js +713 -0
  407. package/dist/lib/email/template.js.map +1 -0
  408. package/dist/lib/engine/adr36.d.ts +56 -0
  409. package/dist/lib/engine/adr36.d.ts.map +1 -0
  410. package/dist/lib/engine/adr36.js +76 -0
  411. package/dist/lib/engine/adr36.js.map +1 -0
  412. package/dist/lib/engine/client.d.ts +162 -0
  413. package/dist/lib/engine/client.d.ts.map +1 -0
  414. package/dist/lib/engine/client.js +473 -0
  415. package/dist/lib/engine/client.js.map +1 -0
  416. package/dist/lib/engine/types.d.ts +1356 -0
  417. package/dist/lib/engine/types.d.ts.map +1 -0
  418. package/dist/lib/engine/types.js +562 -0
  419. package/dist/lib/engine/types.js.map +1 -0
  420. package/dist/lib/errors.d.ts +73 -0
  421. package/dist/lib/errors.d.ts.map +1 -0
  422. package/dist/lib/errors.js +96 -0
  423. package/dist/lib/errors.js.map +1 -0
  424. package/dist/lib/facts/builder.d.ts +88 -0
  425. package/dist/lib/facts/builder.d.ts.map +1 -0
  426. package/dist/lib/facts/builder.js +239 -0
  427. package/dist/lib/facts/builder.js.map +1 -0
  428. package/dist/lib/facts/ctx.d.ts +34 -0
  429. package/dist/lib/facts/ctx.d.ts.map +1 -0
  430. package/dist/lib/facts/ctx.js +51 -0
  431. package/dist/lib/facts/ctx.js.map +1 -0
  432. package/dist/lib/facts/expected.d.ts +23 -0
  433. package/dist/lib/facts/expected.d.ts.map +1 -0
  434. package/dist/lib/facts/expected.js +16 -0
  435. package/dist/lib/facts/expected.js.map +1 -0
  436. package/dist/lib/facts/fact-cache.d.ts +469 -0
  437. package/dist/lib/facts/fact-cache.d.ts.map +1 -0
  438. package/dist/lib/facts/fact-cache.js +52 -0
  439. package/dist/lib/facts/fact-cache.js.map +1 -0
  440. package/dist/lib/facts/factset.d.ts +608 -0
  441. package/dist/lib/facts/factset.d.ts.map +1 -0
  442. package/dist/lib/facts/factset.js +226 -0
  443. package/dist/lib/facts/factset.js.map +1 -0
  444. package/dist/lib/facts/producer.d.ts +190 -0
  445. package/dist/lib/facts/producer.d.ts.map +1 -0
  446. package/dist/lib/facts/producer.js +15 -0
  447. package/dist/lib/facts/producer.js.map +1 -0
  448. package/dist/lib/facts/runner.d.ts +111 -0
  449. package/dist/lib/facts/runner.d.ts.map +1 -0
  450. package/dist/lib/facts/runner.js +438 -0
  451. package/dist/lib/facts/runner.js.map +1 -0
  452. package/dist/lib/facts/stock/ai-check.d.ts +100 -0
  453. package/dist/lib/facts/stock/ai-check.d.ts.map +1 -0
  454. package/dist/lib/facts/stock/ai-check.js +526 -0
  455. package/dist/lib/facts/stock/ai-check.js.map +1 -0
  456. package/dist/lib/facts/stock/ai-inputs.d.ts +104 -0
  457. package/dist/lib/facts/stock/ai-inputs.d.ts.map +1 -0
  458. package/dist/lib/facts/stock/ai-inputs.js +332 -0
  459. package/dist/lib/facts/stock/ai-inputs.js.map +1 -0
  460. package/dist/lib/facts/stock/ai-provider.d.ts +105 -0
  461. package/dist/lib/facts/stock/ai-provider.d.ts.map +1 -0
  462. package/dist/lib/facts/stock/ai-provider.js +250 -0
  463. package/dist/lib/facts/stock/ai-provider.js.map +1 -0
  464. package/dist/lib/facts/stock/ai-unique.d.ts +85 -0
  465. package/dist/lib/facts/stock/ai-unique.d.ts.map +1 -0
  466. package/dist/lib/facts/stock/ai-unique.js +208 -0
  467. package/dist/lib/facts/stock/ai-unique.js.map +1 -0
  468. package/dist/lib/facts/stock/archive.d.ts +63 -0
  469. package/dist/lib/facts/stock/archive.d.ts.map +1 -0
  470. package/dist/lib/facts/stock/archive.js +349 -0
  471. package/dist/lib/facts/stock/archive.js.map +1 -0
  472. package/dist/lib/facts/stock/c2pa-trust-list.d.ts +16 -0
  473. package/dist/lib/facts/stock/c2pa-trust-list.d.ts.map +1 -0
  474. package/dist/lib/facts/stock/c2pa-trust-list.js +637 -0
  475. package/dist/lib/facts/stock/c2pa-trust-list.js.map +1 -0
  476. package/dist/lib/facts/stock/c2pa.d.ts +56 -0
  477. package/dist/lib/facts/stock/c2pa.d.ts.map +1 -0
  478. package/dist/lib/facts/stock/c2pa.js +234 -0
  479. package/dist/lib/facts/stock/c2pa.js.map +1 -0
  480. package/dist/lib/facts/stock/call.d.ts +91 -0
  481. package/dist/lib/facts/stock/call.d.ts.map +1 -0
  482. package/dist/lib/facts/stock/call.js +281 -0
  483. package/dist/lib/facts/stock/call.js.map +1 -0
  484. package/dist/lib/facts/stock/capability.d.ts +39 -0
  485. package/dist/lib/facts/stock/capability.d.ts.map +1 -0
  486. package/dist/lib/facts/stock/capability.js +59 -0
  487. package/dist/lib/facts/stock/capability.js.map +1 -0
  488. package/dist/lib/facts/stock/ext-source.d.ts +51 -0
  489. package/dist/lib/facts/stock/ext-source.d.ts.map +1 -0
  490. package/dist/lib/facts/stock/ext-source.js +201 -0
  491. package/dist/lib/facts/stock/ext-source.js.map +1 -0
  492. package/dist/lib/facts/stock/frequency-fact.d.ts +59 -0
  493. package/dist/lib/facts/stock/frequency-fact.d.ts.map +1 -0
  494. package/dist/lib/facts/stock/frequency-fact.js +86 -0
  495. package/dist/lib/facts/stock/frequency-fact.js.map +1 -0
  496. package/dist/lib/facts/stock/frequency.d.ts +32 -0
  497. package/dist/lib/facts/stock/frequency.d.ts.map +1 -0
  498. package/dist/lib/facts/stock/frequency.js +48 -0
  499. package/dist/lib/facts/stock/frequency.js.map +1 -0
  500. package/dist/lib/facts/stock/index.d.ts +27 -0
  501. package/dist/lib/facts/stock/index.d.ts.map +1 -0
  502. package/dist/lib/facts/stock/index.js +28 -0
  503. package/dist/lib/facts/stock/index.js.map +1 -0
  504. package/dist/lib/facts/stock/normalize.d.ts +45 -0
  505. package/dist/lib/facts/stock/normalize.d.ts.map +1 -0
  506. package/dist/lib/facts/stock/normalize.js +135 -0
  507. package/dist/lib/facts/stock/normalize.js.map +1 -0
  508. package/dist/lib/facts/stock/phash.d.ts +55 -0
  509. package/dist/lib/facts/stock/phash.d.ts.map +1 -0
  510. package/dist/lib/facts/stock/phash.js +256 -0
  511. package/dist/lib/facts/stock/phash.js.map +1 -0
  512. package/dist/lib/facts/stock/rule-defaults.d.ts +72 -0
  513. package/dist/lib/facts/stock/rule-defaults.d.ts.map +1 -0
  514. package/dist/lib/facts/stock/rule-defaults.js +55 -0
  515. package/dist/lib/facts/stock/rule-defaults.js.map +1 -0
  516. package/dist/lib/facts/stock/send.d.ts +52 -0
  517. package/dist/lib/facts/stock/send.d.ts.map +1 -0
  518. package/dist/lib/facts/stock/send.js +148 -0
  519. package/dist/lib/facts/stock/send.js.map +1 -0
  520. package/dist/lib/facts/stock/unique-score.d.ts +138 -0
  521. package/dist/lib/facts/stock/unique-score.d.ts.map +1 -0
  522. package/dist/lib/facts/stock/unique-score.js +257 -0
  523. package/dist/lib/facts/stock/unique-score.js.map +1 -0
  524. package/dist/lib/facts/stock/unique-store.d.ts +420 -0
  525. package/dist/lib/facts/stock/unique-store.d.ts.map +1 -0
  526. package/dist/lib/facts/stock/unique-store.js +328 -0
  527. package/dist/lib/facts/stock/unique-store.js.map +1 -0
  528. package/dist/lib/facts/stock/unique.d.ts +35 -0
  529. package/dist/lib/facts/stock/unique.d.ts.map +1 -0
  530. package/dist/lib/facts/stock/unique.js +327 -0
  531. package/dist/lib/facts/stock/unique.js.map +1 -0
  532. package/dist/lib/facts/tools.d.ts +57 -0
  533. package/dist/lib/facts/tools.d.ts.map +1 -0
  534. package/dist/lib/facts/tools.js +325 -0
  535. package/dist/lib/facts/tools.js.map +1 -0
  536. package/dist/lib/facts/validate.d.ts +33 -0
  537. package/dist/lib/facts/validate.d.ts.map +1 -0
  538. package/dist/lib/facts/validate.js +137 -0
  539. package/dist/lib/facts/validate.js.map +1 -0
  540. package/dist/lib/hash.d.ts +44 -0
  541. package/dist/lib/hash.d.ts.map +1 -0
  542. package/dist/lib/hash.js +80 -0
  543. package/dist/lib/hash.js.map +1 -0
  544. package/dist/lib/http/client.d.ts +113 -0
  545. package/dist/lib/http/client.d.ts.map +1 -0
  546. package/dist/lib/http/client.js +330 -0
  547. package/dist/lib/http/client.js.map +1 -0
  548. package/dist/lib/ids.d.ts +17 -0
  549. package/dist/lib/ids.d.ts.map +1 -0
  550. package/dist/lib/ids.js +26 -0
  551. package/dist/lib/ids.js.map +1 -0
  552. package/dist/lib/ixo/attachments.d.ts +116 -0
  553. package/dist/lib/ixo/attachments.d.ts.map +1 -0
  554. package/dist/lib/ixo/attachments.js +290 -0
  555. package/dist/lib/ixo/attachments.js.map +1 -0
  556. package/dist/lib/ixo/authz.d.ts +40 -0
  557. package/dist/lib/ixo/authz.d.ts.map +1 -0
  558. package/dist/lib/ixo/authz.js +113 -0
  559. package/dist/lib/ixo/authz.js.map +1 -0
  560. package/dist/lib/ixo/blocksync/index.d.ts +90 -0
  561. package/dist/lib/ixo/blocksync/index.d.ts.map +1 -0
  562. package/dist/lib/ixo/blocksync/index.js +251 -0
  563. package/dist/lib/ixo/blocksync/index.js.map +1 -0
  564. package/dist/lib/ixo/blocksync/queries.d.ts +15 -0
  565. package/dist/lib/ixo/blocksync/queries.d.ts.map +1 -0
  566. package/dist/lib/ixo/blocksync/queries.js +144 -0
  567. package/dist/lib/ixo/blocksync/queries.js.map +1 -0
  568. package/dist/lib/ixo/blocksync/types.d.ts +184 -0
  569. package/dist/lib/ixo/blocksync/types.d.ts.map +1 -0
  570. package/dist/lib/ixo/blocksync/types.js +108 -0
  571. package/dist/lib/ixo/blocksync/types.js.map +1 -0
  572. package/dist/lib/ixo/cellnode.d.ts +35 -0
  573. package/dist/lib/ixo/cellnode.d.ts.map +1 -0
  574. package/dist/lib/ixo/cellnode.js +43 -0
  575. package/dist/lib/ixo/cellnode.js.map +1 -0
  576. package/dist/lib/ixo/chain-write.d.ts +130 -0
  577. package/dist/lib/ixo/chain-write.d.ts.map +1 -0
  578. package/dist/lib/ixo/chain-write.js +460 -0
  579. package/dist/lib/ixo/chain-write.js.map +1 -0
  580. package/dist/lib/ixo/chain.d.ts +1046 -0
  581. package/dist/lib/ixo/chain.d.ts.map +1 -0
  582. package/dist/lib/ixo/chain.js +279 -0
  583. package/dist/lib/ixo/chain.js.map +1 -0
  584. package/dist/lib/ixo/claim-bot.d.ts +49 -0
  585. package/dist/lib/ixo/claim-bot.d.ts.map +1 -0
  586. package/dist/lib/ixo/claim-bot.js +141 -0
  587. package/dist/lib/ixo/claim-bot.js.map +1 -0
  588. package/dist/lib/ixo/delegation-verify.d.ts +44 -0
  589. package/dist/lib/ixo/delegation-verify.d.ts.map +1 -0
  590. package/dist/lib/ixo/delegation-verify.js +101 -0
  591. package/dist/lib/ixo/delegation-verify.js.map +1 -0
  592. package/dist/lib/ixo/did.d.ts +13 -0
  593. package/dist/lib/ixo/did.d.ts.map +1 -0
  594. package/dist/lib/ixo/did.js +85 -0
  595. package/dist/lib/ixo/did.js.map +1 -0
  596. package/dist/lib/ixo/grant-chain.d.ts +55 -0
  597. package/dist/lib/ixo/grant-chain.d.ts.map +1 -0
  598. package/dist/lib/ixo/grant-chain.js +185 -0
  599. package/dist/lib/ixo/grant-chain.js.map +1 -0
  600. package/dist/lib/ixo/identity.d.ts +32 -0
  601. package/dist/lib/ixo/identity.d.ts.map +1 -0
  602. package/dist/lib/ixo/identity.js +104 -0
  603. package/dist/lib/ixo/identity.js.map +1 -0
  604. package/dist/lib/ixo/index.d.ts +118 -0
  605. package/dist/lib/ixo/index.d.ts.map +1 -0
  606. package/dist/lib/ixo/index.js +395 -0
  607. package/dist/lib/ixo/index.js.map +1 -0
  608. package/dist/lib/ixo/payment.d.ts +104 -0
  609. package/dist/lib/ixo/payment.d.ts.map +1 -0
  610. package/dist/lib/ixo/payment.js +136 -0
  611. package/dist/lib/ixo/payment.js.map +1 -0
  612. package/dist/lib/ixo/ucan-store.d.ts +30 -0
  613. package/dist/lib/ixo/ucan-store.d.ts.map +1 -0
  614. package/dist/lib/ixo/ucan-store.js +134 -0
  615. package/dist/lib/ixo/ucan-store.js.map +1 -0
  616. package/dist/lib/ixo/ucan.d.ts +96 -0
  617. package/dist/lib/ixo/ucan.d.ts.map +1 -0
  618. package/dist/lib/ixo/ucan.js +216 -0
  619. package/dist/lib/ixo/ucan.js.map +1 -0
  620. package/dist/lib/ixo/verified-read.d.ts +43 -0
  621. package/dist/lib/ixo/verified-read.d.ts.map +1 -0
  622. package/dist/lib/ixo/verified-read.js +73 -0
  623. package/dist/lib/ixo/verified-read.js.map +1 -0
  624. package/dist/lib/ixo/vfs.d.ts +27 -0
  625. package/dist/lib/ixo/vfs.d.ts.map +1 -0
  626. package/dist/lib/ixo/vfs.js +42 -0
  627. package/dist/lib/ixo/vfs.js.map +1 -0
  628. package/dist/lib/ixo/web-did.d.ts +7 -0
  629. package/dist/lib/ixo/web-did.d.ts.map +1 -0
  630. package/dist/lib/ixo/web-did.js +9 -0
  631. package/dist/lib/ixo/web-did.js.map +1 -0
  632. package/dist/lib/logger.d.ts +34 -0
  633. package/dist/lib/logger.d.ts.map +1 -0
  634. package/dist/lib/logger.js +126 -0
  635. package/dist/lib/logger.js.map +1 -0
  636. package/dist/lib/matrix/api.d.ts +57 -0
  637. package/dist/lib/matrix/api.d.ts.map +1 -0
  638. package/dist/lib/matrix/api.js +58 -0
  639. package/dist/lib/matrix/api.js.map +1 -0
  640. package/dist/lib/matrix/client.d.ts +41 -0
  641. package/dist/lib/matrix/client.d.ts.map +1 -0
  642. package/dist/lib/matrix/client.js +104 -0
  643. package/dist/lib/matrix/client.js.map +1 -0
  644. package/dist/lib/matrix/deliver.d.ts +224 -0
  645. package/dist/lib/matrix/deliver.d.ts.map +1 -0
  646. package/dist/lib/matrix/deliver.js +788 -0
  647. package/dist/lib/matrix/deliver.js.map +1 -0
  648. package/dist/lib/matrix/events.d.ts +114 -0
  649. package/dist/lib/matrix/events.d.ts.map +1 -0
  650. package/dist/lib/matrix/events.js +143 -0
  651. package/dist/lib/matrix/events.js.map +1 -0
  652. package/dist/lib/matrix/mxid.d.ts +24 -0
  653. package/dist/lib/matrix/mxid.d.ts.map +1 -0
  654. package/dist/lib/matrix/mxid.js +47 -0
  655. package/dist/lib/matrix/mxid.js.map +1 -0
  656. package/dist/lib/metrics.d.ts +105 -0
  657. package/dist/lib/metrics.d.ts.map +1 -0
  658. package/dist/lib/metrics.js +204 -0
  659. package/dist/lib/metrics.js.map +1 -0
  660. package/dist/lib/oauth/approvals.d.ts +160 -0
  661. package/dist/lib/oauth/approvals.d.ts.map +1 -0
  662. package/dist/lib/oauth/approvals.js +273 -0
  663. package/dist/lib/oauth/approvals.js.map +1 -0
  664. package/dist/lib/oauth/standing.d.ts +152 -0
  665. package/dist/lib/oauth/standing.d.ts.map +1 -0
  666. package/dist/lib/oauth/standing.js +299 -0
  667. package/dist/lib/oauth/standing.js.map +1 -0
  668. package/dist/lib/oauth/token.d.ts +60 -0
  669. package/dist/lib/oauth/token.d.ts.map +1 -0
  670. package/dist/lib/oauth/token.js +129 -0
  671. package/dist/lib/oauth/token.js.map +1 -0
  672. package/dist/lib/payments/extend.d.ts +42 -0
  673. package/dist/lib/payments/extend.d.ts.map +1 -0
  674. package/dist/lib/payments/extend.js +98 -0
  675. package/dist/lib/payments/extend.js.map +1 -0
  676. package/dist/lib/payments/facilitator.d.ts +220 -0
  677. package/dist/lib/payments/facilitator.d.ts.map +1 -0
  678. package/dist/lib/payments/facilitator.js +451 -0
  679. package/dist/lib/payments/facilitator.js.map +1 -0
  680. package/dist/lib/payments/gate.d.ts +207 -0
  681. package/dist/lib/payments/gate.d.ts.map +1 -0
  682. package/dist/lib/payments/gate.js +481 -0
  683. package/dist/lib/payments/gate.js.map +1 -0
  684. package/dist/lib/payments/header-seal.d.ts +33 -0
  685. package/dist/lib/payments/header-seal.d.ts.map +1 -0
  686. package/dist/lib/payments/header-seal.js +76 -0
  687. package/dist/lib/payments/header-seal.js.map +1 -0
  688. package/dist/lib/payments/index.d.ts +12 -0
  689. package/dist/lib/payments/index.d.ts.map +1 -0
  690. package/dist/lib/payments/index.js +11 -0
  691. package/dist/lib/payments/index.js.map +1 -0
  692. package/dist/lib/payments/price.d.ts +25 -0
  693. package/dist/lib/payments/price.d.ts.map +1 -0
  694. package/dist/lib/payments/price.js +43 -0
  695. package/dist/lib/payments/price.js.map +1 -0
  696. package/dist/lib/payments/reconcile.d.ts +77 -0
  697. package/dist/lib/payments/reconcile.d.ts.map +1 -0
  698. package/dist/lib/payments/reconcile.js +317 -0
  699. package/dist/lib/payments/reconcile.js.map +1 -0
  700. package/dist/lib/payments/refund.d.ts +34 -0
  701. package/dist/lib/payments/refund.d.ts.map +1 -0
  702. package/dist/lib/payments/refund.js +123 -0
  703. package/dist/lib/payments/refund.js.map +1 -0
  704. package/dist/lib/payments/review-billing.d.ts +222 -0
  705. package/dist/lib/payments/review-billing.d.ts.map +1 -0
  706. package/dist/lib/payments/review-billing.js +609 -0
  707. package/dist/lib/payments/review-billing.js.map +1 -0
  708. package/dist/lib/payments/settle.d.ts +44 -0
  709. package/dist/lib/payments/settle.d.ts.map +1 -0
  710. package/dist/lib/payments/settle.js +306 -0
  711. package/dist/lib/payments/settle.js.map +1 -0
  712. package/dist/lib/payments/terms.d.ts +27 -0
  713. package/dist/lib/payments/terms.d.ts.map +1 -0
  714. package/dist/lib/payments/terms.js +21 -0
  715. package/dist/lib/payments/terms.js.map +1 -0
  716. package/dist/lib/payouts.d.ts +20 -0
  717. package/dist/lib/payouts.d.ts.map +1 -0
  718. package/dist/lib/payouts.js +30 -0
  719. package/dist/lib/payouts.js.map +1 -0
  720. package/dist/lib/readiness.d.ts +42 -0
  721. package/dist/lib/readiness.d.ts.map +1 -0
  722. package/dist/lib/readiness.js +130 -0
  723. package/dist/lib/readiness.js.map +1 -0
  724. package/dist/lib/redact.d.ts +23 -0
  725. package/dist/lib/redact.d.ts.map +1 -0
  726. package/dist/lib/redact.js +67 -0
  727. package/dist/lib/redact.js.map +1 -0
  728. package/dist/lib/register.d.ts +85 -0
  729. package/dist/lib/register.d.ts.map +1 -0
  730. package/dist/lib/register.js +390 -0
  731. package/dist/lib/register.js.map +1 -0
  732. package/dist/lib/review/attestation.d.ts +92 -0
  733. package/dist/lib/review/attestation.d.ts.map +1 -0
  734. package/dist/lib/review/attestation.js +264 -0
  735. package/dist/lib/review/attestation.js.map +1 -0
  736. package/dist/lib/review/reviewer-grant.d.ts +146 -0
  737. package/dist/lib/review/reviewer-grant.d.ts.map +1 -0
  738. package/dist/lib/review/reviewer-grant.js +359 -0
  739. package/dist/lib/review/reviewer-grant.js.map +1 -0
  740. package/dist/lib/review/tasks.d.ts +18 -0
  741. package/dist/lib/review/tasks.d.ts.map +1 -0
  742. package/dist/lib/review/tasks.js +36 -0
  743. package/dist/lib/review/tasks.js.map +1 -0
  744. package/dist/lib/sentry.d.ts +89 -0
  745. package/dist/lib/sentry.d.ts.map +1 -0
  746. package/dist/lib/sentry.js +284 -0
  747. package/dist/lib/sentry.js.map +1 -0
  748. package/dist/lib/spans.d.ts +14 -0
  749. package/dist/lib/spans.d.ts.map +1 -0
  750. package/dist/lib/spans.js +28 -0
  751. package/dist/lib/spans.js.map +1 -0
  752. package/dist/lib/tracing.d.ts +31 -0
  753. package/dist/lib/tracing.d.ts.map +1 -0
  754. package/dist/lib/tracing.js +66 -0
  755. package/dist/lib/tracing.js.map +1 -0
  756. package/dist/lib/ttl-cache.d.ts +26 -0
  757. package/dist/lib/ttl-cache.d.ts.map +1 -0
  758. package/dist/lib/ttl-cache.js +61 -0
  759. package/dist/lib/ttl-cache.js.map +1 -0
  760. package/dist/lib/validator.d.ts +19 -0
  761. package/dist/lib/validator.d.ts.map +1 -0
  762. package/dist/lib/validator.js +32 -0
  763. package/dist/lib/validator.js.map +1 -0
  764. package/dist/lib/work-order/form.d.ts +40 -0
  765. package/dist/lib/work-order/form.d.ts.map +1 -0
  766. package/dist/lib/work-order/form.js +316 -0
  767. package/dist/lib/work-order/form.js.map +1 -0
  768. package/dist/lib/work-order/index.d.ts +20 -0
  769. package/dist/lib/work-order/index.d.ts.map +1 -0
  770. package/dist/lib/work-order/index.js +66 -0
  771. package/dist/lib/work-order/index.js.map +1 -0
  772. package/dist/middleware/api/audit.d.ts +9 -0
  773. package/dist/middleware/api/audit.d.ts.map +1 -0
  774. package/dist/middleware/api/audit.js +38 -0
  775. package/dist/middleware/api/audit.js.map +1 -0
  776. package/dist/middleware/api/auth.d.ts +29 -0
  777. package/dist/middleware/api/auth.d.ts.map +1 -0
  778. package/dist/middleware/api/auth.js +105 -0
  779. package/dist/middleware/api/auth.js.map +1 -0
  780. package/dist/middleware/api/console.d.ts +92 -0
  781. package/dist/middleware/api/console.d.ts.map +1 -0
  782. package/dist/middleware/api/console.js +446 -0
  783. package/dist/middleware/api/console.js.map +1 -0
  784. package/dist/middleware/api/errors.d.ts +48 -0
  785. package/dist/middleware/api/errors.d.ts.map +1 -0
  786. package/dist/middleware/api/errors.js +133 -0
  787. package/dist/middleware/api/errors.js.map +1 -0
  788. package/dist/middleware/api/idempotency.d.ts +23 -0
  789. package/dist/middleware/api/idempotency.d.ts.map +1 -0
  790. package/dist/middleware/api/idempotency.js +158 -0
  791. package/dist/middleware/api/idempotency.js.map +1 -0
  792. package/dist/middleware/api/keys.d.ts +14 -0
  793. package/dist/middleware/api/keys.d.ts.map +1 -0
  794. package/dist/middleware/api/keys.js +66 -0
  795. package/dist/middleware/api/keys.js.map +1 -0
  796. package/dist/middleware/api/membership.d.ts +32 -0
  797. package/dist/middleware/api/membership.d.ts.map +1 -0
  798. package/dist/middleware/api/membership.js +48 -0
  799. package/dist/middleware/api/membership.js.map +1 -0
  800. package/dist/middleware/api/oauth.d.ts +28 -0
  801. package/dist/middleware/api/oauth.d.ts.map +1 -0
  802. package/dist/middleware/api/oauth.js +109 -0
  803. package/dist/middleware/api/oauth.js.map +1 -0
  804. package/dist/middleware/api/rate-limit.d.ts +23 -0
  805. package/dist/middleware/api/rate-limit.d.ts.map +1 -0
  806. package/dist/middleware/api/rate-limit.js +70 -0
  807. package/dist/middleware/api/rate-limit.js.map +1 -0
  808. package/dist/middleware/api/types.d.ts +92 -0
  809. package/dist/middleware/api/types.d.ts.map +1 -0
  810. package/dist/middleware/api/types.js +7 -0
  811. package/dist/middleware/api/types.js.map +1 -0
  812. package/dist/middleware/api/wait.d.ts +21 -0
  813. package/dist/middleware/api/wait.d.ts.map +1 -0
  814. package/dist/middleware/api/wait.js +85 -0
  815. package/dist/middleware/api/wait.js.map +1 -0
  816. package/dist/middleware/capability.d.ts +32 -0
  817. package/dist/middleware/capability.d.ts.map +1 -0
  818. package/dist/middleware/capability.js +113 -0
  819. package/dist/middleware/capability.js.map +1 -0
  820. package/dist/middleware/database.d.ts +14 -0
  821. package/dist/middleware/database.d.ts.map +1 -0
  822. package/dist/middleware/database.js +18 -0
  823. package/dist/middleware/database.js.map +1 -0
  824. package/dist/middleware/error-handler.d.ts +13 -0
  825. package/dist/middleware/error-handler.d.ts.map +1 -0
  826. package/dist/middleware/error-handler.js +127 -0
  827. package/dist/middleware/error-handler.js.map +1 -0
  828. package/dist/middleware/observability.d.ts +32 -0
  829. package/dist/middleware/observability.d.ts.map +1 -0
  830. package/dist/middleware/observability.js +134 -0
  831. package/dist/middleware/observability.js.map +1 -0
  832. package/dist/middleware/rate-limit.d.ts +16 -0
  833. package/dist/middleware/rate-limit.d.ts.map +1 -0
  834. package/dist/middleware/rate-limit.js +56 -0
  835. package/dist/middleware/rate-limit.js.map +1 -0
  836. package/dist/middleware/ucan-auth.d.ts +39 -0
  837. package/dist/middleware/ucan-auth.d.ts.map +1 -0
  838. package/dist/middleware/ucan-auth.js +278 -0
  839. package/dist/middleware/ucan-auth.js.map +1 -0
  840. package/dist/networks.d.ts +34 -0
  841. package/dist/networks.d.ts.map +1 -0
  842. package/dist/networks.js +49 -0
  843. package/dist/networks.js.map +1 -0
  844. package/dist/oracle.d.ts +193 -0
  845. package/dist/oracle.d.ts.map +1 -0
  846. package/dist/oracle.js +245 -0
  847. package/dist/oracle.js.map +1 -0
  848. package/dist/routes/health.d.ts +16 -0
  849. package/dist/routes/health.d.ts.map +1 -0
  850. package/dist/routes/health.js +29 -0
  851. package/dist/routes/health.js.map +1 -0
  852. package/dist/routes/v1/admin.d.ts +18 -0
  853. package/dist/routes/v1/admin.d.ts.map +1 -0
  854. package/dist/routes/v1/admin.js +101 -0
  855. package/dist/routes/v1/admin.js.map +1 -0
  856. package/dist/routes/v1/api/admin-claims.d.ts +14 -0
  857. package/dist/routes/v1/api/admin-claims.d.ts.map +1 -0
  858. package/dist/routes/v1/api/admin-claims.js +82 -0
  859. package/dist/routes/v1/api/admin-claims.js.map +1 -0
  860. package/dist/routes/v1/api/admin-facilitator.d.ts +20 -0
  861. package/dist/routes/v1/api/admin-facilitator.d.ts.map +1 -0
  862. package/dist/routes/v1/api/admin-facilitator.js +64 -0
  863. package/dist/routes/v1/api/admin-facilitator.js.map +1 -0
  864. package/dist/routes/v1/api/admin.d.ts +9 -0
  865. package/dist/routes/v1/api/admin.d.ts.map +1 -0
  866. package/dist/routes/v1/api/admin.js +110 -0
  867. package/dist/routes/v1/api/admin.js.map +1 -0
  868. package/dist/routes/v1/api/audit.d.ts +8 -0
  869. package/dist/routes/v1/api/audit.d.ts.map +1 -0
  870. package/dist/routes/v1/api/audit.js +56 -0
  871. package/dist/routes/v1/api/audit.js.map +1 -0
  872. package/dist/routes/v1/api/batch.d.ts +17 -0
  873. package/dist/routes/v1/api/batch.d.ts.map +1 -0
  874. package/dist/routes/v1/api/batch.js +192 -0
  875. package/dist/routes/v1/api/batch.js.map +1 -0
  876. package/dist/routes/v1/api/claims-read.d.ts +43 -0
  877. package/dist/routes/v1/api/claims-read.d.ts.map +1 -0
  878. package/dist/routes/v1/api/claims-read.js +123 -0
  879. package/dist/routes/v1/api/claims-read.js.map +1 -0
  880. package/dist/routes/v1/api/claims.d.ts +131 -0
  881. package/dist/routes/v1/api/claims.d.ts.map +1 -0
  882. package/dist/routes/v1/api/claims.js +407 -0
  883. package/dist/routes/v1/api/claims.js.map +1 -0
  884. package/dist/routes/v1/api/collections-link.d.ts +14 -0
  885. package/dist/routes/v1/api/collections-link.d.ts.map +1 -0
  886. package/dist/routes/v1/api/collections-link.js +97 -0
  887. package/dist/routes/v1/api/collections-link.js.map +1 -0
  888. package/dist/routes/v1/api/export.d.ts +48 -0
  889. package/dist/routes/v1/api/export.d.ts.map +1 -0
  890. package/dist/routes/v1/api/export.js +251 -0
  891. package/dist/routes/v1/api/export.js.map +1 -0
  892. package/dist/routes/v1/api/index.d.ts +16 -0
  893. package/dist/routes/v1/api/index.d.ts.map +1 -0
  894. package/dist/routes/v1/api/index.js +68 -0
  895. package/dist/routes/v1/api/index.js.map +1 -0
  896. package/dist/routes/v1/api/keys.d.ts +9 -0
  897. package/dist/routes/v1/api/keys.d.ts.map +1 -0
  898. package/dist/routes/v1/api/keys.js +95 -0
  899. package/dist/routes/v1/api/keys.js.map +1 -0
  900. package/dist/routes/v1/api/me.d.ts +21 -0
  901. package/dist/routes/v1/api/me.d.ts.map +1 -0
  902. package/dist/routes/v1/api/me.js +122 -0
  903. package/dist/routes/v1/api/me.js.map +1 -0
  904. package/dist/routes/v1/api/members.d.ts +17 -0
  905. package/dist/routes/v1/api/members.d.ts.map +1 -0
  906. package/dist/routes/v1/api/members.js +406 -0
  907. package/dist/routes/v1/api/members.js.map +1 -0
  908. package/dist/routes/v1/api/meta.d.ts +12 -0
  909. package/dist/routes/v1/api/meta.d.ts.map +1 -0
  910. package/dist/routes/v1/api/meta.js +59 -0
  911. package/dist/routes/v1/api/meta.js.map +1 -0
  912. package/dist/routes/v1/api/openapi.gen.d.ts +2 -0
  913. package/dist/routes/v1/api/openapi.gen.d.ts.map +1 -0
  914. package/dist/routes/v1/api/openapi.gen.js +7 -0
  915. package/dist/routes/v1/api/openapi.gen.js.map +1 -0
  916. package/dist/routes/v1/api/protocols.d.ts +22 -0
  917. package/dist/routes/v1/api/protocols.d.ts.map +1 -0
  918. package/dist/routes/v1/api/protocols.js +153 -0
  919. package/dist/routes/v1/api/protocols.js.map +1 -0
  920. package/dist/routes/v1/api/review-billing.d.ts +18 -0
  921. package/dist/routes/v1/api/review-billing.d.ts.map +1 -0
  922. package/dist/routes/v1/api/review-billing.js +196 -0
  923. package/dist/routes/v1/api/review-billing.js.map +1 -0
  924. package/dist/routes/v1/api/review.d.ts +30 -0
  925. package/dist/routes/v1/api/review.d.ts.map +1 -0
  926. package/dist/routes/v1/api/review.js +302 -0
  927. package/dist/routes/v1/api/review.js.map +1 -0
  928. package/dist/routes/v1/api/sources.d.ts +10 -0
  929. package/dist/routes/v1/api/sources.d.ts.map +1 -0
  930. package/dist/routes/v1/api/sources.js +293 -0
  931. package/dist/routes/v1/api/sources.js.map +1 -0
  932. package/dist/routes/v1/api/uploads.d.ts +37 -0
  933. package/dist/routes/v1/api/uploads.d.ts.map +1 -0
  934. package/dist/routes/v1/api/uploads.js +414 -0
  935. package/dist/routes/v1/api/uploads.js.map +1 -0
  936. package/dist/routes/v1/api/views.d.ts +18 -0
  937. package/dist/routes/v1/api/views.d.ts.map +1 -0
  938. package/dist/routes/v1/api/views.js +95 -0
  939. package/dist/routes/v1/api/views.js.map +1 -0
  940. package/dist/routes/v1/api/webhooks.d.ts +14 -0
  941. package/dist/routes/v1/api/webhooks.d.ts.map +1 -0
  942. package/dist/routes/v1/api/webhooks.js +282 -0
  943. package/dist/routes/v1/api/webhooks.js.map +1 -0
  944. package/dist/routes/v1/api/work-orders.d.ts +45 -0
  945. package/dist/routes/v1/api/work-orders.d.ts.map +1 -0
  946. package/dist/routes/v1/api/work-orders.js +171 -0
  947. package/dist/routes/v1/api/work-orders.js.map +1 -0
  948. package/dist/routes/v1/claims.d.ts +21 -0
  949. package/dist/routes/v1/claims.d.ts.map +1 -0
  950. package/dist/routes/v1/claims.js +153 -0
  951. package/dist/routes/v1/claims.js.map +1 -0
  952. package/dist/routes/v1/collections.d.ts +45 -0
  953. package/dist/routes/v1/collections.d.ts.map +1 -0
  954. package/dist/routes/v1/collections.js +201 -0
  955. package/dist/routes/v1/collections.js.map +1 -0
  956. package/dist/routes/v1/index.d.ts +13 -0
  957. package/dist/routes/v1/index.d.ts.map +1 -0
  958. package/dist/routes/v1/index.js +41 -0
  959. package/dist/routes/v1/index.js.map +1 -0
  960. package/dist/routes/v1/info.d.ts +14 -0
  961. package/dist/routes/v1/info.d.ts.map +1 -0
  962. package/dist/routes/v1/info.js +75 -0
  963. package/dist/routes/v1/info.js.map +1 -0
  964. package/dist/routes/v1/mcp/index.d.ts +33 -0
  965. package/dist/routes/v1/mcp/index.d.ts.map +1 -0
  966. package/dist/routes/v1/mcp/index.js +252 -0
  967. package/dist/routes/v1/mcp/index.js.map +1 -0
  968. package/dist/routes/v1/mcp/oauth.d.ts +27 -0
  969. package/dist/routes/v1/mcp/oauth.d.ts.map +1 -0
  970. package/dist/routes/v1/mcp/oauth.js +500 -0
  971. package/dist/routes/v1/mcp/oauth.js.map +1 -0
  972. package/dist/routes/v1/mcp/tools.d.ts +71 -0
  973. package/dist/routes/v1/mcp/tools.d.ts.map +1 -0
  974. package/dist/routes/v1/mcp/tools.js +432 -0
  975. package/dist/routes/v1/mcp/tools.js.map +1 -0
  976. package/dist/routes/v1/mcp/ui.d.ts +45 -0
  977. package/dist/routes/v1/mcp/ui.d.ts.map +1 -0
  978. package/dist/routes/v1/mcp/ui.js +454 -0
  979. package/dist/routes/v1/mcp/ui.js.map +1 -0
  980. package/dist/routes/v1/oauth.d.ts +29 -0
  981. package/dist/routes/v1/oauth.d.ts.map +1 -0
  982. package/dist/routes/v1/oauth.js +256 -0
  983. package/dist/routes/v1/oauth.js.map +1 -0
  984. package/dist/routes/v1/reviewers.d.ts +22 -0
  985. package/dist/routes/v1/reviewers.d.ts.map +1 -0
  986. package/dist/routes/v1/reviewers.js +165 -0
  987. package/dist/routes/v1/reviewers.js.map +1 -0
  988. package/dist/routes/v1/reviews.d.ts +38 -0
  989. package/dist/routes/v1/reviews.d.ts.map +1 -0
  990. package/dist/routes/v1/reviews.js +234 -0
  991. package/dist/routes/v1/reviews.js.map +1 -0
  992. package/dist/routes/v1/shared.d.ts +586 -0
  993. package/dist/routes/v1/shared.d.ts.map +1 -0
  994. package/dist/routes/v1/shared.js +229 -0
  995. package/dist/routes/v1/shared.js.map +1 -0
  996. package/dist/routes/well-known.d.ts +15 -0
  997. package/dist/routes/well-known.d.ts.map +1 -0
  998. package/dist/routes/well-known.js +35 -0
  999. package/dist/routes/well-known.js.map +1 -0
  1000. package/dist/runtime.d.ts +100 -0
  1001. package/dist/runtime.d.ts.map +1 -0
  1002. package/dist/runtime.js +144 -0
  1003. package/dist/runtime.js.map +1 -0
  1004. package/dist/testing/fake-tools.d.ts +104 -0
  1005. package/dist/testing/fake-tools.d.ts.map +1 -0
  1006. package/dist/testing/fake-tools.js +213 -0
  1007. package/dist/testing/fake-tools.js.map +1 -0
  1008. package/dist/testing/index.d.ts +54 -0
  1009. package/dist/testing/index.d.ts.map +1 -0
  1010. package/dist/testing/index.js +104 -0
  1011. package/dist/testing/index.js.map +1 -0
  1012. package/dist/testing/samples.d.ts +70 -0
  1013. package/dist/testing/samples.d.ts.map +1 -0
  1014. package/dist/testing/samples.js +92 -0
  1015. package/dist/testing/samples.js.map +1 -0
  1016. package/dist/workflows/claim-ingest.d.ts +250 -0
  1017. package/dist/workflows/claim-ingest.d.ts.map +1 -0
  1018. package/dist/workflows/claim-ingest.js +1020 -0
  1019. package/dist/workflows/claim-ingest.js.map +1 -0
  1020. package/dist/workflows/claim-source.d.ts +25 -0
  1021. package/dist/workflows/claim-source.d.ts.map +1 -0
  1022. package/dist/workflows/claim-source.js +107 -0
  1023. package/dist/workflows/claim-source.js.map +1 -0
  1024. package/dist/workflows/review-complete.d.ts +82 -0
  1025. package/dist/workflows/review-complete.d.ts.map +1 -0
  1026. package/dist/workflows/review-complete.js +455 -0
  1027. package/dist/workflows/review-complete.js.map +1 -0
  1028. package/dist/workflows/steps.d.ts +125 -0
  1029. package/dist/workflows/steps.d.ts.map +1 -0
  1030. package/dist/workflows/steps.js +325 -0
  1031. package/dist/workflows/steps.js.map +1 -0
  1032. package/docs/api.md +2595 -0
  1033. package/docs/guide.md +1525 -0
  1034. package/migrations/0000_init.sql +108 -0
  1035. package/migrations/0001_review_attestation.sql +1 -0
  1036. package/migrations/0002_decisions_facts.sql +1 -0
  1037. package/migrations/0003_api_lane.sql +171 -0
  1038. package/migrations/0004_api_v1_1.sql +19 -0
  1039. package/migrations/0005_member_notify.sql +3 -0
  1040. package/migrations/0006_source_collections.sql +16 -0
  1041. package/migrations/0007_api_settlement.sql +27 -0
  1042. package/migrations/0008_review_extend.sql +1 -0
  1043. package/migrations/0009_card_refunds.sql +4 -0
  1044. package/migrations/0010_even_scorpion.sql +16 -0
  1045. package/migrations/0011_mcp_oauth.sql +27 -0
  1046. package/migrations/0012_mcp_standing.sql +21 -0
  1047. package/migrations/0013_unknown_krista_starr.sql +2 -0
  1048. package/migrations/0014_last_carnage.sql +14 -0
  1049. package/migrations/0015_company_authority.sql +26 -0
  1050. package/migrations/0016_owner_only_links.sql +6 -0
  1051. package/migrations/0017_organisations.sql +35 -0
  1052. package/migrations/0018_remove_app_signed.sql +4 -0
  1053. package/migrations/0019_submitted_via.sql +2 -0
  1054. package/migrations/0020_drop_decision_to_pay.sql +4 -0
  1055. package/migrations/0021_manual_erase.sql +25 -0
  1056. package/migrations/0022_errored_facts.sql +1 -0
  1057. package/migrations/0023_review_billing.sql +20 -0
  1058. package/migrations/0024_pending_task_details.sql +1 -0
  1059. package/migrations/meta/0000_snapshot.json +707 -0
  1060. package/migrations/meta/0001_snapshot.json +714 -0
  1061. package/migrations/meta/0002_snapshot.json +721 -0
  1062. package/migrations/meta/0003_snapshot.json +1845 -0
  1063. package/migrations/meta/0004_snapshot.json +1969 -0
  1064. package/migrations/meta/0005_snapshot.json +1991 -0
  1065. package/migrations/meta/0006_snapshot.json +2097 -0
  1066. package/migrations/meta/0007_snapshot.json +2128 -0
  1067. package/migrations/meta/0008_snapshot.json +2133 -0
  1068. package/migrations/meta/0009_snapshot.json +2161 -0
  1069. package/migrations/meta/0010_snapshot.json +2265 -0
  1070. package/migrations/meta/0011_snapshot.json +2448 -0
  1071. package/migrations/meta/0012_snapshot.json +2577 -0
  1072. package/migrations/meta/0013_snapshot.json +2594 -0
  1073. package/migrations/meta/0014_snapshot.json +2602 -0
  1074. package/migrations/meta/0015_snapshot.json +2778 -0
  1075. package/migrations/meta/0016_snapshot.json +2778 -0
  1076. package/migrations/meta/0017_snapshot.json +2792 -0
  1077. package/migrations/meta/0018_snapshot.json +2778 -0
  1078. package/migrations/meta/0019_snapshot.json +2792 -0
  1079. package/migrations/meta/0020_snapshot.json +2785 -0
  1080. package/migrations/meta/0021_snapshot.json +2762 -0
  1081. package/migrations/meta/0022_snapshot.json +2769 -0
  1082. package/migrations/meta/0023_snapshot.json +2900 -0
  1083. package/migrations/meta/0024_snapshot.json +2907 -0
  1084. package/migrations/meta/_journal.json +181 -0
  1085. package/openapi/decision-api.yaml +12204 -0
  1086. package/package.json +123 -4
  1087. package/skills/README.md +19 -0
  1088. package/skills/add-openhands-support/SKILL.md +113 -0
  1089. package/skills/create-collection/SKILL.md +199 -0
  1090. package/skills/create-collection/reference/claims-stack.md +106 -0
  1091. package/skills/create-collection/reference/collection.md +111 -0
  1092. package/skills/create-oracle/SKILL.md +400 -0
  1093. package/skills/create-rubric/SKILL.md +130 -0
  1094. package/skills/create-rubric/reference/format-cheatsheet.md +186 -0
  1095. package/skills/create-rubric/templates/claim-form.example.json +60 -0
  1096. package/skills/decision-api-client/SKILL.md +236 -0
  1097. package/skills/decision-api-oracle/SKILL.md +336 -0
  1098. package/skills/publish-protocol/SKILL.md +151 -0
  1099. package/skills/publish-protocol/reference/publishing.md +116 -0
  1100. package/skills/reference/engine-contract.md +222 -0
  1101. package/skills/write-facts/SKILL.md +221 -0
  1102. package/skills/write-facts/reference/examples/http-vendor.ts +88 -0
  1103. package/skills/write-facts/reference/examples/price-matches-agreement.ts +67 -0
  1104. package/skills/write-facts/reference/facts-api.md +232 -0
  1105. package/templates/project/.dev.vars.example +93 -0
  1106. package/templates/project/.editorconfig +9 -0
  1107. package/templates/project/CLAUDE.md +45 -0
  1108. package/templates/project/README.md +199 -0
  1109. package/templates/project/biome.json +37 -0
  1110. package/templates/project/gitignore +29 -0
  1111. package/templates/project/package.json +32 -0
  1112. package/templates/project/src/facts/index.ts +19 -0
  1113. package/templates/project/src/index.ts +25 -0
  1114. package/templates/project/test/api-lane.test.ts +57 -0
  1115. package/templates/project/test/facts.test.ts +14 -0
  1116. package/templates/project/tsconfig.json +25 -0
  1117. package/templates/project/vitest.config.ts +13 -0
  1118. package/templates/project/wrangler.jsonc +446 -0
@@ -0,0 +1,1433 @@
1
+ /**
2
+ * Database schema — the source of truth. Edit here → `bun run db:generate` → `bun run db:migrate`.
3
+ *
4
+ * Cloudflare D1 (SQLite): tables are `sqliteTable` from `drizzle-orm/sqlite-core`; timestamps are
5
+ * `integer({ mode: "timestamp_ms" })`, booleans `integer({ mode: "boolean" })`, JSON columns
6
+ * `text({ mode: "json" })`. Columns are written snake_case from camelCase field names (the
7
+ * `casing` option in drizzle.config.ts and db/client.ts). Enums are `text({ enum })` — SQLite has
8
+ * no enum type, so the allowed values are enforced by the type and the app, not the database.
9
+ *
10
+ * Timestamps default app-side (`$defaultFn` / `$onUpdate`): every write goes through Drizzle, and
11
+ * a JS `Date` keeps millisecond precision without depending on which SQLite `unixepoch()` variant
12
+ * the D1 build carries.
13
+ *
14
+ * D1 has NO documented transaction atomicity through `db.transaction()` (each statement auto-commits);
15
+ * a multi-statement write that must be atomic goes through `db.batch([...])`. Every write in this
16
+ * schema is designed as ONE statement (`onConflictDoNothing` / `onConflictDoUpdate`), so nothing
17
+ * here needs a transaction at all.
18
+ */
19
+ import { sql } from "drizzle-orm";
20
+ import { index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from "drizzle-orm/sqlite-core";
21
+ /**
22
+ * Collections this oracle has been hired to evaluate (README "How a claim flows" step 1). Upserted on
23
+ * `collectionId` by `POST /v1/collections/register`: `ownerDid` is the CHAIN owner (who deposits
24
+ * the owner→oracle delegation in the UCAN Store), `enrolledByDid` whoever passed the register
25
+ * gates. This is the poll-set the cron scans, and the authority the read path trusts for the
26
+ * delegation root.
27
+ */
28
+ export const watchedCollections = sqliteTable("watched_collections", {
29
+ collectionId: text().primaryKey(),
30
+ /**
31
+ * The CHAIN owner's wallet DID (`entity.owner` of the collection's deed entity) — who pays the
32
+ * evaluation fees, and the delegation root we look up when reading this collection's claims.
33
+ * Always the chain's answer, never the enroller's.
34
+ */
35
+ ownerDid: text().notNull(),
36
+ /**
37
+ * Who registered it — the principal that signed the register: the owner, or a holder of an
38
+ * active evaluate grant for the collection. Admitted by the read gate beside the owner; NEVER
39
+ * the delegation root (that stays the owner's, above — the Matrix delegation is theirs).
40
+ */
41
+ enrolledByDid: text().notNull(),
42
+ /**
43
+ * The collection's on-chain evaluation payment as accepted at (re-)register — what this
44
+ * collection pays per `MsgEvaluateClaim` (the chain splits it 80/10/10 to the oracle). Checked
45
+ * against the oracle config's `pricing` on every register; recorded so the dashboard can show it.
46
+ */
47
+ evaluationDenom: text(),
48
+ evaluationAmount: text(),
49
+ /** Protocol entity DID backing the collection (blocksync `collection.protocol`) — where `#rub` is anchored. */
50
+ protocolDid: text(),
51
+ /**
52
+ * The pinned rubric: sha256 of its stored bytes, which IS its id and the on-chain
53
+ * LinkedResource `proof`. Pinned by the workflow's evaluate step on first sight; the chain is the
54
+ * authority. Null until
55
+ * resolved.
56
+ */
57
+ rubricId: text(),
58
+ /**
59
+ * The owner→oracle delegation (base64 CAR), persisted at register time so the read path makes
60
+ * ZERO UCAN-Store round trips. Refreshed from the store when missing/expired (the portal still
61
+ * deposits there — the store stays the fleet registry and our refresh source).
62
+ */
63
+ delegationCar: text(),
64
+ /** When the stored delegation expires (null = it declares no expiry). */
65
+ delegationExpiresAt: integer({ mode: "timestamp_ms" }),
66
+ /** Where the commissioner is reached (review requests, pauses). Captured at register. */
67
+ contactEmail: text(),
68
+ /**
69
+ * `paused` stops the scan enqueuing anything for this collection — the engine answering 402
70
+ * (credits exhausted) or 403 (not hired) flips it, an operator flips it back. The row and its
71
+ * delegation stand.
72
+ */
73
+ status: text({ enum: ["active", "paused"] })
74
+ .notNull()
75
+ .default("active"),
76
+ /**
77
+ * WHY the engine paused it, for the operator and the dashboard: `engine-credits` (402 — every
78
+ * active collection pauses, resume after the top-up), `engine-no-grant` (403 — this oracle
79
+ * lost the collection's `EvaluateClaimAuthorization`; re-register once re-granted) or
80
+ * `rubric-unusable` (the engine's rubric manifest is `unusable`, or a 200 `decision.status:
81
+ * "unusable"` — the engine cannot resolve/bind the protocol's rubric to its form / the facts;
82
+ * every claim would be refused the same way, so the broken catalog entry is paid for at most
83
+ * once; resume once `#rub`/`#vct` are fixed) or `admin-unfunded` (the chain refused our
84
+ * `MsgEvaluateClaim` with "insufficient funds: payment withdrawal failed" — the collection's
85
+ * admin account cannot pay the evaluation leg, and every further decision would be billed by
86
+ * the engine and then parked the same way; `cron/funding.ts` resumes it and re-delivers the
87
+ * parked decisions once the account covers `evaluationAmount`), or — per-review billing
88
+ * (`billingSourceId` set) — `payer-credits` (the facilitator refused the reservation for want of
89
+ * the paying organisation's credits: a top-up fixes it) or `payer-delegation` (no usable
90
+ * review-billing delegation: none, expired, cap used up, its signer no longer the
91
+ * organisation's owner, the company disputed, no published price — a new delegation in the
92
+ * Console fixes it), or `oracle-plan` (the facilitator says IXO's plan does not let this
93
+ * oracle bill reviews: IXO's to fix, paged, the owner not told); `cron/payer-billing.ts`
94
+ * resumes all three. Null on an
95
+ * operator pause; cleared on resume/re-register. A TEXT column: the enum is type-only (SQLite),
96
+ * so a new value needs no migration.
97
+ */
98
+ pausedReason: text({
99
+ enum: [
100
+ "engine-credits",
101
+ "engine-no-grant",
102
+ "rubric-unusable",
103
+ "admin-unfunded",
104
+ "payer-credits",
105
+ "payer-delegation",
106
+ "oracle-plan",
107
+ ],
108
+ }),
109
+ /**
110
+ * Per-review checker billing (IXO's plan for the oracle, payments/review-billing.ts): the
111
+ * Decision API source whose stored delegation pays for each of this collection's claims over
112
+ * x402 — set at register when the collection's company (the engine's answer) holds one, so the
113
+ * collection registered with an empty evaluation leg. Null = the chain's evaluation payment pays
114
+ * (today's model; never both). Re-resolved on every claim's reservation, and written again if
115
+ * the organisation's paying source changed.
116
+ */
117
+ billingSourceId: text(),
118
+ /**
119
+ * The cron scan watermark: the newest claim `submissionDate` we've enqueued for this
120
+ * collection. Null = never scanned, so the next tick sweeps the collection from the beginning.
121
+ * Scans are inclusive (`>=`) so claims sharing a timestamp are never skipped; `claim_ingests`
122
+ * is the forever dedup that stops the boundary claim being re-pulled.
123
+ */
124
+ cursor: text(),
125
+ /**
126
+ * The cron rotation clock: stamped on EVERY visit (found claims, found nothing, or failed).
127
+ * Ticks pick the least-recently-scanned collections first, so a bounded per-tick batch still
128
+ * covers every watched collection fairly. Null = never scanned → front of the queue.
129
+ */
130
+ lastScannedAt: integer({ mode: "timestamp_ms" }),
131
+ /**
132
+ * Whether the act seam's on-chain amount may stand (company authority D7, F6): `off` — the
133
+ * default, the owner never said yes — ignores it for the lane's default and logs it. Set by the
134
+ * collection OWNER only (`PATCH /v1/collections/:id/settings`), enforced by the act lane
135
+ * (chain-write.ts). A TEXT column: the enum is type-only (SQLite).
136
+ */
137
+ operatorAmounts: text({ enum: ["off", "allowed"] })
138
+ .notNull()
139
+ .default("off"),
140
+ /**
141
+ * Who set `operatorAmounts` — the chain owner's address as the settings route checked it. The
142
+ * act lane honours `allowed` only while this is STILL the collection's live owner, so a yes
143
+ * never outlives an ownership transfer: the new owner has to say it again (D7).
144
+ */
145
+ operatorAmountsBy: text(),
146
+ createdAt: integer({ mode: "timestamp_ms" })
147
+ .notNull()
148
+ .$defaultFn(() => new Date()),
149
+ updatedAt: integer({ mode: "timestamp_ms" })
150
+ .notNull()
151
+ .$defaultFn(() => new Date())
152
+ .$onUpdate(() => new Date()),
153
+ }, (t) => [
154
+ // The cron's rotation read: active rows, least recently scanned first.
155
+ index("watched_collections_status_last_scanned_idx").on(t.status, t.lastScannedAt),
156
+ ]);
157
+ /**
158
+ * The ingestion ledger: one row per claim we've ever accepted, and where it got to.
159
+ *
160
+ * This — not the existence of a Workflow instance — is the source of truth for "have we got this
161
+ * claim already?", because instances are retained only 3–30 days; after that the runtime would
162
+ * happily accept the same id again and we'd silently re-ingest forever.
163
+ *
164
+ * The workflow owns its row for its whole lifecycle (record-queued → … → mark-processed); the
165
+ * cron never writes it. The cron's only dedupe is "row exists → already started", plus the
166
+ * workflow instance id's own idempotency. The claim is taken by INSERTing here with
167
+ * `onConflictDoNothing()` — one statement, so the primary key is the mutex: no select-then-insert
168
+ * race, and no matching on error strings.
169
+ */
170
+ export const claimIngests = sqliteTable("claim_ingests", {
171
+ claimId: text().primaryKey(),
172
+ collectionId: text().notNull(),
173
+ status: text({ enum: ["queued", "processing", "processed", "failed", "skipped"] })
174
+ .notNull()
175
+ .default("queued"),
176
+ /**
177
+ * How the claim arrived (Go Prod §7.1): `chain` (the cron scan) or `api` (`POST /v1/api/claims`,
178
+ * `collectionId` = the scope id `api:<sourceId>:<protocolDid>`). `ReviewComplete` reads it to
179
+ * pick the `ClaimSource` its re-pull goes through. Defaulted, so every pre-existing row and every
180
+ * cron insert that never names it stays `chain`.
181
+ */
182
+ lane: text({ enum: ["chain", "api"] })
183
+ .notNull()
184
+ .default("chain"),
185
+ /** The Workflow instance id (the claimId, or its sha256 — lib/ids.ts), to follow it while it lives. */
186
+ instanceId: text(),
187
+ /** The terminal failure's message, for the claim read and the operator — null unless `failed`. */
188
+ error: text(),
189
+ /**
190
+ * When the collection's owner erased this CHAIN claim's answer copies (company authority F14,
191
+ * `DELETE /v1/claims/:claimId/body`, lib/claim-erase.ts): the fact transcripts on
192
+ * `decisions.facts` and the registry's `normalizedText`. Null = never erased — the oracle never
193
+ * erases chain-lane data on its own. The body itself was never stored here (it lives on the
194
+ * claim's own store). Never set on an `api` row — that lane's marker is `api_claims.bodyErasedAt`.
195
+ */
196
+ erasedAt: integer({ mode: "timestamp_ms" }),
197
+ createdAt: integer({ mode: "timestamp_ms" })
198
+ .notNull()
199
+ .$defaultFn(() => new Date()),
200
+ updatedAt: integer({ mode: "timestamp_ms" })
201
+ .notNull()
202
+ .$defaultFn(() => new Date())
203
+ .$onUpdate(() => new Date()),
204
+ }, (t) => [
205
+ // Covers the hot list query (`GET /v1/claims`, routes/v1/claims.ts): filtered by collectionId,
206
+ // ordered by (createdAt, claimId) desc for keyset pagination. Same leading column as the
207
+ // single-column index this replaces, so it serves an equality-only lookup on collectionId
208
+ // too (e.g. a future one) — no need to keep both.
209
+ index("claim_ingests_collection_created_claim_idx").on(t.collectionId, t.createdAt, t.claimId),
210
+ // The operator's claim list (`GET /v1/api/admin/claims`, lib/api-lane/claim-list.ts): the
211
+ // chain branch over EVERY watched collection is `lane = 'chain'` ordered by (createdAt,
212
+ // claimId) desc — without it that page is a full scan and sort of the ledger.
213
+ index("claim_ingests_lane_created_claim_idx").on(t.lane, t.createdAt, t.claimId),
214
+ ]);
215
+ /**
216
+ * The engine's decision as returned to THIS oracle (`POST /v1/decisions`, README "How a claim flows" step 5),
217
+ * cached once per claim. The engine's ledger is the authority — this row exists so the act lane,
218
+ * the review fold and the claim read never re-ask for a decision already made. `claimId` PK +
219
+ * `onConflictDoNothing` is the decided-once guard on our side, matching the engine's own
220
+ * evaluated-once mutex. Written once by the evaluate step; changed only by the review fold (the
221
+ * SAME decision with the answers folded in — never a second evaluation) and by delivery state
222
+ * (`chainStatus`/`txHash`/`chainError`).
223
+ *
224
+ * A claim the facts lane could not build for — `unusable` (the engine's rubric manifest says the
225
+ * protocol's rubric cannot be resolved or bound: no `#rub`, swapped bytes, a drifted `#vct` — its
226
+ * issues verbatim), `invalid_facts` (the producer's answer doesn't match the rubric's work order —
227
+ * our/the provider's bug) — gets a row too, with the engine never asked to decide (nothing to
228
+ * decide, nothing charged): `status` names the reason, `explanation` the issues, and every
229
+ * engine-owned column (`rubricId` where unknown, `factsDigest`, `verdict`, `resultDigest`,
230
+ * `decision`) is null. A decide-time `unusable` (the engine's fact-coverage check) is a real
231
+ * decision row (receipt and all); both pause the collection (`watched_collections.pausedReason`).
232
+ */
233
+ export const decisions = sqliteTable("decisions", {
234
+ claimId: text().primaryKey(),
235
+ collectionId: text().notNull(),
236
+ /** The rubric the engine judged against — pinned per claim, so a later re-anchor changes nothing here. */
237
+ rubricId: text(),
238
+ /** sha256(canonicalJson(FactSet)) — what we sent; binds this decision to the facts we produced. */
239
+ factsDigest: text(),
240
+ /** The engine's verdict (approve · partial · reject · review); null on a facts-lane outcome. */
241
+ verdict: text(),
242
+ /**
243
+ * `decided` · `pending_review` · `unusable` from the engine; the facts lane's `unusable` ·
244
+ * `invalid_facts`; or the engine's refusal of the claim's content (company authority) —
245
+ * `content_mismatch` · `payload_too_large`, recorded like a facts-lane outcome (no engine
246
+ * columns, `skipped`). Type-only enum: a new value needs no migration.
247
+ */
248
+ status: text().notNull(),
249
+ /** The engine's `resultDigest` — what a review answer is folded against (`answeredAgainst`). */
250
+ resultDigest: text(),
251
+ /** The engine's signed receipt CID — what `MsgEvaluateClaim.verification_proof` carries. */
252
+ receiptCid: text(),
253
+ /**
254
+ * The receipt itself — the engine's Ed25519 compact JWS (codes, scores, identifiers; never
255
+ * answer values). The receipt is the engine's product and the artifact this oracle acted on,
256
+ * so the oracle holds it: `GET /v1/claims/:claimId` serves it, and a Matrix republish of the
257
+ * CID (a follow-up) needs the bytes. Written together with `receiptCid`, always.
258
+ */
259
+ receiptJws: text(),
260
+ /** The engine's decision object verbatim (codes, scores, outcomes — never answer values). */
261
+ decision: text({ mode: "json" }).$type(),
262
+ /** The engine's plain-English narrative, display-only. */
263
+ explanation: text(),
264
+ /**
265
+ * The `ext`/`ai` facts this decision was made on, frozen exactly as they went to the engine
266
+ * (never `answers`/`attachments` — this row outlives the claim's erasable surface). The act
267
+ * policy (act.ts) reads them by name at signing time, which is why they cannot live in the
268
+ * connector cache: that dies in the same batch that writes this row (claim-ingest.ts `record`).
269
+ * Null ONLY on a row the engine never decided — a facts-lane `unusable`/`invalid_facts`, which
270
+ * is `skipped` from the start; a `decided` row without them is an ingest contract violation and
271
+ * the act lane parks it rather than sign blind.
272
+ */
273
+ facts: text({ mode: "json" }).$type(),
274
+ /**
275
+ * The engine's `erroredFacts` (engine/types.ts `ErroredFact`): each errored fact's lane-prefixed
276
+ * name and its own error text, each detail capped — WHY a claim was held, which the engine's
277
+ * hashed reason line never says. Only the derived list, never facts or answers; written in the
278
+ * decision's own statement (and replaced by a fold that carries one). Null when nothing errored
279
+ * or the engine sent none (an older engine).
280
+ */
281
+ erroredFacts: text({ mode: "json" }).$type(),
282
+ /**
283
+ * The engine's `pendingTaskDetails` (engine/types.ts `PendingTaskDetail`): per pending
284
+ * `unique:<ruleId>` task, the duplicate score and the prior claim's id — what the review view's
285
+ * `duplicates` is built from. Written with the decision only (a fold always answers `{}`:
286
+ * nothing pends after it). Null when none pends or the engine sent none (an older engine).
287
+ */
288
+ pendingTaskDetails: text({ mode: "json" }).$type(),
289
+ /**
290
+ * Where the verdict got to on chain: `pending` (not yet acted on) → `submitted` (our tx) /
291
+ * `blocked` (broadcast failed, retryable) / `skipped` (AUTO_SIGN off, or a non-terminal
292
+ * verdict) / `held` (the oracle's act policy is keeping it back for a later `signEvaluation` —
293
+ * NOT a delivered state) / `owner_submitted` (someone else evaluated it first — the chain locks
294
+ * a claim on its first terminal evaluation). A TEXT column: the enum is type-only (SQLite), so a
295
+ * new value needs no migration.
296
+ */
297
+ chainStatus: text({
298
+ enum: ["pending", "submitted", "blocked", "skipped", "held", "owner_submitted"],
299
+ })
300
+ .notNull()
301
+ .default("pending"),
302
+ txHash: text(),
303
+ /** The last delivery failure (a `blocked` reason, or the broadcast error the step is retrying); null once submitted. */
304
+ chainError: text(),
305
+ createdAt: integer({ mode: "timestamp_ms" })
306
+ .notNull()
307
+ .$defaultFn(() => new Date()),
308
+ updatedAt: integer({ mode: "timestamp_ms" })
309
+ .notNull()
310
+ .$defaultFn(() => new Date())
311
+ .$onUpdate(() => new Date()),
312
+ }, (t) => [
313
+ // The review-reminder sweep (Go Prod §10.4: 3 and 14 days) and the operator's pending list:
314
+ // rows in one status, oldest first.
315
+ index("decisions_status_created_idx").on(t.status, t.createdAt),
316
+ // The funding cron's parked decisions of one collection (cron/funding.ts `redeliverParked`:
317
+ // collection + `chainStatus in (pending, blocked)`, oldest first) — without it every resume
318
+ // walked the whole table.
319
+ index("dec_collection_chain").on(t.collectionId, t.chainStatus, t.createdAt),
320
+ ]);
321
+ /**
322
+ * Human-review answers + their fold (README "How a claim flows" step 6). The decision row stays as the engine
323
+ * returned it — the fold is recorded BESIDE it. `claimId` PK = the answered-once mutex
324
+ * (`onConflictDoNothing`): the POST is idempotent until folded, then conflicts. `foldedAt` is
325
+ * written once by the `ReviewComplete` workflow when the engine has folded the answers.
326
+ */
327
+ export const claimReviews = sqliteTable("claim_reviews", {
328
+ claimId: text().primaryKey(),
329
+ /** `{ [taskId]: boolean | string }` — covers EXACTLY the decision's pending review tasks. */
330
+ answers: text({ mode: "json" }).$type().notNull(),
331
+ /** From the UCAN principal. Our word alone unless `attestationJws` backs it. */
332
+ reviewerDid: text().notNull(),
333
+ /**
334
+ * The reviewer's signed attestation over `answers` (compact JWS, design §B.3) — stored VERBATIM
335
+ * because the signature is over exact bytes; null for a review answered without one (optional
336
+ * this round). Erasable with this row: it is the one place answer VALUES are signed, which is why
337
+ * the receipt and the Matrix card carry only its CID.
338
+ */
339
+ attestationJws: text(),
340
+ answeredAt: integer({ mode: "timestamp_ms" })
341
+ .notNull()
342
+ .$defaultFn(() => new Date()),
343
+ foldedAt: integer({ mode: "timestamp_ms" }),
344
+ /**
345
+ * Why the fold did not land (the engine's `STALE_REVIEW` — the answers named a digest the engine
346
+ * no longer holds — or a validation refusal), surfaced on `GET /v1/reviews/:claimId` so the
347
+ * reviewer can answer again; a re-POST clears it.
348
+ */
349
+ foldError: text(),
350
+ /**
351
+ * The reviewer's grant (company authority D2): base64 CAR, one link, controller → reviewer
352
+ * did:ixo, as `ReviewerGrant` in lib/engine/types.ts — the bytes the controller FILED
353
+ * (`collection_reviewers.delegation`), never the reviewer's copy. Stored with the answers so a
354
+ * retried fold forwards the same proof. Erasable with the row.
355
+ */
356
+ reviewerGrant: text(),
357
+ });
358
+ /**
359
+ * A chain collection's reviewers (company authority D2, F2, F12): each row one signed delegation
360
+ * from a root the engine accepts (`rootDid` — the collection owner or an entity controller) to a
361
+ * member `did:ixo`, kept with what it says (`expiresAt`) so a check needs no CAR parse — as
362
+ * `api_members` keeps a source's grants. The CID is the identity: a re-grant is a new row, and
363
+ * revoking stamps `revokedAt` (a row is never edited otherwise). Read by (collection, member) when a
364
+ * review is answered; enforced from CA-M3.
365
+ */
366
+ export const collectionReviewers = sqliteTable("collection_reviewers", {
367
+ collectionId: text().notNull(),
368
+ /** The member's `did:ixo` the delegation names as audience. */
369
+ memberDid: text().notNull(),
370
+ /** Who signed it: the root the engine checks against the chain. */
371
+ rootDid: text().notNull(),
372
+ /** Base64 of the delegation CAR. */
373
+ delegation: text().notNull(),
374
+ delegationCid: text().notNull(),
375
+ /** The delegation's expiry, in ms (`exp * 1000`). Required: a reviewer grant never lives forever. */
376
+ expiresAt: integer({ mode: "timestamp_ms" }).notNull(),
377
+ revokedAt: integer({ mode: "timestamp_ms" }),
378
+ createdAt: integer({ mode: "timestamp_ms" })
379
+ .notNull()
380
+ .$defaultFn(() => new Date()),
381
+ }, (t) => [
382
+ primaryKey({ columns: [t.collectionId, t.delegationCid] }),
383
+ // The review gate: this member's grants on this collection.
384
+ index("collection_reviewers_member_idx").on(t.collectionId, t.memberDid),
385
+ ]);
386
+ /**
387
+ * Canonical-body registry for duplicate detection (duplicate spec §9; the registry is
388
+ * oracle-side — docs/ENGINE-CONTRACT.md "Fact coverage + manifest") — one row per
389
+ * (collection, digest, claim), written by the stock producer's resolve phase BEFORE it reads
390
+ * siblings (insert-self-first, spec §3.2): two racing claims each see the other, so neither can
391
+ * slip through the race window. `onConflictDoNothing` on the PK makes the insert idempotent under
392
+ * workflow step retry. The prior-claim scope is every claim THIS oracle ingested for the
393
+ * collection — the D1 is this oracle's, so no oracle column is needed and no other oracle's
394
+ * registry is ever visible.
395
+ *
396
+ * `digest` is the keyed HMAC over the canonical body — matching digests mean matching content,
397
+ * but the digest alone reveals nothing (spec §12.3). `normalizedText` is the near-text lane's
398
+ * haystack and the ONLY column carrying claim-derived text: erasable PII, nullable by design —
399
+ * wiping it degrades fuzzy recall for old rows without touching the exact-match lane.
400
+ * `finalVerdict` is denormalized when the engine's decision lands (workflows, never the producer)
401
+ * so the `countPrior` filter reads one table; NULL means still pending, which counts as blockable.
402
+ *
403
+ * Indexes: the composite PK already serves the (collection, digest) exact lookup (SQLite's
404
+ * autoindex covers a leading prefix); `cbd_recent` serves the near-text pool read (newest rows of
405
+ * a collection first — lib/facts/stock/unique-store.ts, where Postgres had a GIN trigram index);
406
+ * `cbd_claim` serves every read keyed on the claim — the workflows' `finalVerdict` UPDATE (every
407
+ * decided claim), the CID lane's join and the erase routes (`claim_id = ?` alone,
408
+ * hence claimId leading). The PK cannot: `digest` sits between collection and claim, so each of
409
+ * them walked every registry row of the collection, or of the table.
410
+ */
411
+ export const claimBodyDigests = sqliteTable("claim_body_digests", {
412
+ collectionId: text().notNull(),
413
+ /** HMAC-SHA256 over the canonical body (spec §4.1) — the exact-match lane's key. */
414
+ digest: text().notNull(),
415
+ claimId: text().notNull(),
416
+ agentAddress: text(),
417
+ /** Near-text lane haystack; erasable PII — nullable by design (spec §12.3). */
418
+ normalizedText: text(),
419
+ /** Denormalized at decision time (registry token: approved · rejected · pending_review); NULL = pending, blockable. */
420
+ finalVerdict: text(),
421
+ createdAt: integer({ mode: "timestamp_ms" })
422
+ .notNull()
423
+ .$defaultFn(() => new Date()),
424
+ }, (t) => [
425
+ primaryKey({ columns: [t.collectionId, t.digest, t.claimId] }),
426
+ index("cbd_recent").on(t.collectionId, t.createdAt),
427
+ index("cbd_claim").on(t.claimId, t.collectionId),
428
+ ]);
429
+ /**
430
+ * Attachment-CID registry (duplicate spec §9, §4 L2) — one row per (collection, cid, claim),
431
+ * same insert-self-first + retry-idempotent discipline as `claim_body_digests`. A CID seen on
432
+ * two different claims IS the same bytes (content addressing does the proving) — no fetch
433
+ * needed. `phash` is the perceptual dHash for the near-match lane (§4 L4): nullable because not
434
+ * every attachment decodes (non-image, oversized, undecodable — and every PDF here: the kit has
435
+ * no Browser Run binding, so PDFs are never rendered) and a missing hash only narrows recall,
436
+ * never blocks registration. `cac_recent` serves the bounded pHash pool read (newest first).
437
+ */
438
+ export const claimAttachmentCids = sqliteTable("claim_attachment_cids", {
439
+ collectionId: text().notNull(),
440
+ cid: text().notNull(),
441
+ claimId: text().notNull(),
442
+ agentAddress: text(),
443
+ /** dHash64 hex (16 chars) of the decoded image; null = not hashable. */
444
+ phash: text(),
445
+ /**
446
+ * The ATTACHMENT's own media type — what `phash` was derived from, which decides how far
447
+ * apart two hashes may sit and still count (unique-score's §5 tiers): a rendered document is
448
+ * deterministic and moves a bit or two, a photo of the same scene moves much more. NULL only
449
+ * on a row written without one: scored with the looser image tiers.
450
+ */
451
+ mediaType: text(),
452
+ createdAt: integer({ mode: "timestamp_ms" })
453
+ .notNull()
454
+ .$defaultFn(() => new Date()),
455
+ }, (t) => [
456
+ primaryKey({ columns: [t.collectionId, t.cid, t.claimId] }),
457
+ index("cac_recent").on(t.collectionId, t.createdAt),
458
+ ]);
459
+ /**
460
+ * Resolved connector answers, cached per claim while its evaluate step is still in flight — the
461
+ * crash-recovery twin of the engine's decided-once read: `GET /v1/decisions/:claimId` covers a
462
+ * crash AFTER the engine decided, this table covers a crash MID-produce, so a step retry re-runs
463
+ * only the connectors that never answered instead of re-buying every AI/ext call. Written
464
+ * fail-soft by the stock producer as each `ext`/`ai` fact resolves (lib/facts/fact-cache.ts);
465
+ * `unique`/`frequency` are NEVER cached — registry state and calendar windows must be fresh per
466
+ * attempt. The one exception is a `unique-judge` row: the same-event judge's `valid` verdict on ONE
467
+ * (claim, candidate) pair, `name` = the candidate claimId (stock/unique.ts `judgePairs`) — a
468
+ * question about two fixed bodies, so a retry need not pay for it again; the candidate SET is still
469
+ * read fresh. `kind` is a type-only enum on TEXT, so that value needed no migration. Keyed by the
470
+ * manifest's `rubricId` too: an answer is an answer to ONE work order, and a `#rub` re-anchored
471
+ * between two attempts (or the `RUBRIC_PIN_MISMATCH` rebuild, workflows/claim-ingest.ts) is a new
472
+ * one — same-named facts must run again, never come back from the old rubric's sources or
473
+ * instructions. Deleted (every rubric's rows) in the same `db.batch` as the claim's `decisions`
474
+ * row write and on terminal failure: decided or dead, the cache is gone — rows only ever outlive a
475
+ * crashed attempt.
476
+ */
477
+ export const factCache = sqliteTable("fact_cache", {
478
+ claimId: text().notNull(),
479
+ /** The work order the row answered (the manifest's `rubricId`, canonical lowercase). */
480
+ rubricId: text().notNull(),
481
+ kind: text({ enum: ["ext", "ai", "unique-judge"] }).notNull(),
482
+ /**
483
+ * The `<name>` in `ext.<name>` / `ai.<name>` — the work-order key (lib/facts/expected.ts); for
484
+ * `unique-judge`, the candidate claimId.
485
+ */
486
+ name: text().notNull(),
487
+ /** The resolved fact (or judgement) verbatim — returned as-is on a retry's hit. */
488
+ fact: text({ mode: "json" }).$type().notNull(),
489
+ createdAt: integer({ mode: "timestamp_ms" })
490
+ .notNull()
491
+ .$defaultFn(() => new Date()),
492
+ }, (t) => [primaryKey({ columns: [t.claimId, t.rubricId, t.kind, t.name] })]);
493
+ /**
494
+ * The side-effect ledger (the review-notification lane, lib/matrix/deliver.ts; the email notices,
495
+ * workflows/steps.ts + routes/v1/collections.ts). `dedupeKey` is
496
+ * the primary key AND the sent-once mutex: a step/route that re-enters finds a `sent` row and does
497
+ * zero HTTP/email. It is ALSO the review room's reuse index — a `sent` `review_room` row is the
498
+ * answer to "does this room already exist" for a `(collectionId, ownerDid)` pair. Kinds:
499
+ *
500
+ * review_room:{collectionId}:{ownerDid} ← the oracle-owned room, reused across every claim
501
+ * review_request:{claimId} ← the sent v2 review-request Matrix event
502
+ * review_fold:{claimId} ← the `m.replace` edit that completes it
503
+ * notice_review_email:{claimId}:{resultDigest} ← the review-request EMAIL twin (deliver.ts),
504
+ * independent of review_request so one lane's
505
+ * failure never blocks or hides the other's
506
+ * notice_paused:{collectionId} ← the paused-collection email (steps.ts)
507
+ * notice_resumed:{collectionId} ← its alternating twin (steps.ts, collections.ts)
508
+ * review_room:{sourceId} ← an API source's review room (Go Prod §10.1), keyed by
509
+ * the source alone: one room per source on this oracle
510
+ * rvi:{sourceId}:{mxid} ← a person invited to it (`review_invite`; the MXID in
511
+ * `targetUrl` too, so a removed member can still be kicked);
512
+ * keyed by MXID, not memberId, so a member removed and
513
+ * re-added is the same row; `dead` once kicked
514
+ * rvm:{claimId} ← the room's notice for one API claim (`review_notice`)
515
+ * rv:{claimId}:{memberId|contact} ← one recipient's review email for one API claim
516
+ * (`review_email`): `sending` once claimed, `pending` while
517
+ * held for the batch (lib/api-lane/reviewers.ts), then its
518
+ * email's outcome
519
+ * rvw:{sourceId} ← the source contact's 15-minute review-email window
520
+ * (`review_window`): `updatedAt` is its last email
521
+ * rv3|rv14:{claimId}:{memberId|contact} ← one recipient's 3-/14-day reminder (`review_reminder`)
522
+ * notice_review_reminder:{claimId}:{3|14} ← an API claim's unanswered-review reminder done (Go Prod
523
+ * §10.4) — what keeps the hourly pass off the claim
524
+ * notice_review_expired:{claimId} ← a paid API claim's review closed unanswered at its
525
+ * `answerBy`, announced (`review_expired` + webhook)
526
+ * notice_balance_low:{sourceId}:{yyyy-mm-dd} ← the `balance.low` email to the source's contact, once a
527
+ * day at most (§12.4; member-emails.ts) — the webhook is
528
+ * once per crossing, keyed by `balanceLowAt`
529
+ * wh:{eventId}:{endpointId|claim} ← one webhook event to one target (`kind: "webhook"`, §4.5)
530
+ * inv:{memberId}:{tokenHash[0,16]} ← an email invite (`member_invite`, member-emails §2); a
531
+ * re-invite mints a new token, so a new row
532
+ * acc:{memberId} ← "invitation accepted" to the inviter (`member_accepted`, §3)
533
+ * grant:{memberId}:{delegationCid} ← "access granted" to the member (`member_granted`, §4)
534
+ *
535
+ * `notice_paused`/`notice_resumed` alternate PER COLLECTION (not per reason, and not owner-pooled
536
+ * like eval-engine v1's billing notices — this kit has one `status` column and no shared
537
+ * subscription/payout accounts to group): a state is announced only when its own marker is not
538
+ * already the newer of the pair, so a step retry inside one pause re-sends nothing and a pause
539
+ * following a recovery is a fresh notice.
540
+ *
541
+ * `resultDigest` is captured ONLY on the `review_request` row, at send time — the PRE-fold digest
542
+ * "the frozen evaluation the reviewer's answers bind to" (events.ts). `deliverReviewFold` reads it
543
+ * back from HERE, never from `decisions.resultDigest`, which the fold has already overwritten with
544
+ * the NEW (post-fold) digest by the time the edit is built.
545
+ *
546
+ * Rows are mutable (attempts/lastError); nothing here ever influences a decision — delivery only,
547
+ * exactly like the engine's own `decisions.chainStatus` lane.
548
+ */
549
+ export const matrixDeliveries = sqliteTable("matrix_deliveries", {
550
+ dedupeKey: text().primaryKey(),
551
+ // A TEXT column: the enum is type-only (SQLite, same note as watched_collections.pausedReason
552
+ // above), so adding a kind needs no migration — `db:generate` reports nothing.
553
+ kind: text({
554
+ enum: [
555
+ "review_room",
556
+ "review_request",
557
+ "review_fold",
558
+ "notice_paused",
559
+ "notice_resumed",
560
+ "notice_review_email",
561
+ "notice_review_reminder",
562
+ "notice_review_expired",
563
+ "review_invite",
564
+ "review_notice",
565
+ "review_email",
566
+ "review_reminder",
567
+ "review_window",
568
+ "member_invite",
569
+ "member_accepted",
570
+ "member_granted",
571
+ "notice_balance_low",
572
+ "notice_review_billing_expiring",
573
+ "notice_review_billing_cap",
574
+ "webhook",
575
+ ],
576
+ }).notNull(),
577
+ claimId: text(),
578
+ collectionId: text(),
579
+ /** The resolved room id — an alias resolved, or `createRoom`'s answer. */
580
+ roomId: text(),
581
+ /** The sent (or edited) event id. */
582
+ eventId: text(),
583
+ /** The `review_request` row's PRE-fold `resultDigest` — see the table header comment. */
584
+ resultDigest: text(),
585
+ /**
586
+ * `pending` and `dead` are the webhook lane's: queued before the first attempt (enqueue sets
587
+ * `nextAttemptAt = now`, so the retry cron's due read finds it even if the first inline attempt
588
+ * never ran), and out of attempts (8 over 24 h, Go Prod §4.5) — the dead-letter the portal
589
+ * shows and a redeliver re-queues. A `failed` webhook row with a `nextAttemptAt` is due for the
590
+ * retry cron. On the wire (`webhook.status`, the delivery log) `sent` reads `delivered`.
591
+ * `sending` is the review/member emails' claim (lib/api-lane/reviewers.ts `claimRows`): the
592
+ * row is written before the send so two callers never both send; a crash mid-send leaves it.
593
+ */
594
+ status: text({ enum: ["sent", "failed", "skipped", "pending", "dead", "sending"] })
595
+ .notNull()
596
+ .default("failed"),
597
+ attempts: integer().notNull().default(0),
598
+ lastError: text(),
599
+ // --- `kind: "webhook"` only (Go Prod §4.5, §6.1); null on every Matrix/email row. The row is
600
+ // `wh:<eventId>:<endpointId>` (or `wh:<eventId>:claim` for a per-claim `webhookUrl`) — one
601
+ // row per event per target, so a redeliver re-queues the same row instead of adding one. ---
602
+ sourceId: text(),
603
+ /** The `webhook_endpoints` row, or null for the claim's own `webhookUrl`. */
604
+ endpointId: text(),
605
+ /** Where it is posted — copied at enqueue, so an endpoint edit never retargets a sent event. */
606
+ targetUrl: text(),
607
+ /** The App. B event type (`claim.decided`, …). */
608
+ eventType: text(),
609
+ /**
610
+ * The signed envelope's JSON, frozen at enqueue so every retry posts the same bytes the
611
+ * `Oracle-Event-Id` promises. Carries the record (metadata included — personal data), so the
612
+ * oracle never deletes the row on its own (owner, 2026-10-11); erasing a claim nulls `payload` and
613
+ * `targetUrl` on its rows too.
614
+ */
615
+ payload: text({ mode: "json" }).$type(),
616
+ /** When the retry cron may attempt it next; null once delivered or dead. */
617
+ nextAttemptAt: integer({ mode: "timestamp_ms" }),
618
+ /** The receiver's last HTTP status (null on a network failure) — the delivery log's column. */
619
+ lastStatusCode: integer(),
620
+ createdAt: integer({ mode: "timestamp_ms" })
621
+ .notNull()
622
+ .$defaultFn(() => new Date()),
623
+ updatedAt: integer({ mode: "timestamp_ms" })
624
+ .notNull()
625
+ .$defaultFn(() => new Date())
626
+ .$onUpdate(() => new Date()),
627
+ }, (t) => [
628
+ index("matrix_deliveries_claim_idx").on(t.claimId),
629
+ // The webhook-retry cron's read: due rows of one kind, oldest due first.
630
+ index("matrix_deliveries_due_idx").on(t.kind, t.status, t.nextAttemptAt),
631
+ // The delivery log (`GET /v1/api/webhooks/deliveries`): one source's rows, newest first.
632
+ index("matrix_deliveries_source_created_idx").on(t.sourceId, t.createdAt),
633
+ // A kind's rows oldest first (the review batch flush, reviewers.ts) without a full scan.
634
+ index("matrix_deliveries_kind_created_idx").on(t.kind, t.createdAt),
635
+ ]);
636
+ // ------------------------------------------------------------------------------------------------
637
+ // The Decision API lane (Go Prod §3, §6.1). Every table below is written only when `API_LANE` is on;
638
+ // with it off they exist empty. An API claim reuses `claim_ingests` / `decisions` / the registries
639
+ // under the scope id `api:<sourceId>:<protocolDid>` in their `collectionId`, so nothing above changes
640
+ // meaning. `sourceId` scopes every read: across sources a row does not exist (404, never 403, §14).
641
+ // ------------------------------------------------------------------------------------------------
642
+ /**
643
+ * One organisation's account with this oracle (Go Prod §3.2) — the API lane's `watched_collections`.
644
+ * `ownerDid` is the IXO account whose deed pays; members and keys hang off `sourceId`.
645
+ */
646
+ export const apiSources = sqliteTable("api_sources", {
647
+ /** `src_<ULID>`. */
648
+ sourceId: text().primaryKey(),
649
+ name: text().notNull(),
650
+ /** The paying IXO account (`did:ixo`) — the root of its members' payment delegations. */
651
+ ownerDid: text().notNull(),
652
+ /**
653
+ * Protocol DIDs this source may submit against (§17). EMPTY = NONE — unlike the chain lane's
654
+ * `supportedProtocols`, where empty means "no restriction": a source can only ever be narrowed to
655
+ * nothing, never opened to everything by an empty list. Sign-up copies the oracle's catalogue.
656
+ */
657
+ allowedProtocols: text({ mode: "json" }).$type().notNull().default([]),
658
+ /**
659
+ * UNUSED since contracts v1.1: there are no per-source prices — every source pays the oracle's
660
+ * published price (payments spec §3.1), and a partner who should not pay gets `billingMode:
661
+ * none`. Kept only because dropping a column is a table rebuild in SQLite.
662
+ */
663
+ priceOverrides: text({ mode: "json" }).$type(),
664
+ /**
665
+ * How the source pays (§3.2): `x402` — an outside customer pays per decision (§11) — or `none` —
666
+ * the operator's own organisation or an unbilled partner: no 402, no `api_charges` row. Set by the
667
+ * oracle's operator only, never by a member: it is a commercial term.
668
+ */
669
+ billingMode: text({ enum: ["x402", "none"] })
670
+ .notNull()
671
+ .default("x402"),
672
+ /** The `balance.low` floor (§12.4), whole cents; null = no alert. */
673
+ refillFloorCents: integer(),
674
+ /**
675
+ * When the balance watch last saw the balance cross BELOW the floor; cleared when it recovers.
676
+ * The watch runs every 15 min — this is what keeps it to one `balance.low` per crossing.
677
+ */
678
+ balanceLowAt: integer({ mode: "timestamp_ms" }),
679
+ /** Default target for claims that name no `webhookUrl` and no endpoint subscribes. */
680
+ webhookUrl: text(),
681
+ /**
682
+ * The source's ONE signing secret for deliveries to a claim's own `webhookUrl` and to the default
683
+ * `webhookUrl` above (§4.5) — encrypted exactly like `webhook_endpoints.secretCiphertext`
684
+ * (`v1:<ciphertext>`), created with the source and shown once. Null for a source created before
685
+ * contracts v1.1: those deliveries then stay `dead` ("no signing secret") until an owner rotates.
686
+ */
687
+ webhookSecretCiphertext: text(),
688
+ /** The secret a rotation replaced, still signing beside the new one for 24 h — as an endpoint's. */
689
+ previousWebhookSecretCiphertext: text(),
690
+ previousWebhookSecretExpiresAt: integer({ mode: "timestamp_ms" }),
691
+ /**
692
+ * D10: a source starts `pending-link` and turns `active` when the company sync reads its
693
+ * organisation's link from the engine; a link for another entity (or the engine's `disputed`)
694
+ * makes it `disputed`. Neither takes claims, keys, invites or webhooks (`409
695
+ * SOURCE_PENDING_LINK` / `SOURCE_DISPUTED`). `paused` answers new submits `503 SOURCE_PAUSED`
696
+ * (App. A); in-flight claims finish. Reasons (paused only) as App. A's `details.reason`:
697
+ * `rubric-unusable`, `engine-credits`, `payments-disabled`, and `operator` for a hand pause from
698
+ * the operator view. TEXT with a type-only enum (no migration), like
699
+ * `watched_collections.pausedReason`.
700
+ */
701
+ status: text({ enum: ["pending-link", "active", "paused", "disputed"] })
702
+ .notNull()
703
+ .default("active"),
704
+ /**
705
+ * The first time the company sync made the source `active`; set once, never cleared (a later
706
+ * `disputed` keeps it). Null ⇒ the source was never active, so its id has never left its
707
+ * organisation's controllers: logs hash it (`sourceLogId`) and only their listing shows it (never
708
+ * the operator's). On the wire as `Source.activatedAt` (1.17.0).
709
+ */
710
+ activatedAt: integer({ mode: "timestamp_ms" }),
711
+ pausedReason: text({
712
+ enum: ["rubric-unusable", "engine-credits", "payments-disabled", "operator"],
713
+ }),
714
+ contactEmail: text(),
715
+ /** Operator-only free text (the operator view); never shown to the source. */
716
+ notes: text(),
717
+ /**
718
+ * The organisation (its on-chain entity) this source belongs to (company authority D1, D10): set
719
+ * at insert by the controller who adds the oracle, never changed. Its CURRENT controllers are the
720
+ * source's roots (`lib/api-lane/company.ts` `sourceRoots`). Nullable in SQL only — a table rebuild
721
+ * to say NOT NULL is not worth its risk: every insert sets it, migration 0017 deleted the rows
722
+ * made before D10, and `sourceView` refuses a null.
723
+ */
724
+ companyEntityDid: text(),
725
+ /**
726
+ * A COPY of the controller-signed `SourceCompanyLink` JWS the engine holds (owner: the engine is
727
+ * the link's single home — the Console PUTs it there, this oracle reads it with `company/read` and
728
+ * never verifies or forwards it). Kept verbatim so a reader can check what the mirror came from.
729
+ */
730
+ companyLink: text(),
731
+ /** The engine's link `issuedAt` as last read — a sync that reads an older one is stale. */
732
+ companyLinkIssuedAt: integer({ mode: "timestamp_ms" }),
733
+ /** A copy of the link's `credentialSubject.payeeField` (D3), for reads; the JWS is the truth. */
734
+ payeeField: text(),
735
+ createdAt: integer({ mode: "timestamp_ms" })
736
+ .notNull()
737
+ .$defaultFn(() => new Date()),
738
+ updatedAt: integer({ mode: "timestamp_ms" })
739
+ .notNull()
740
+ .$defaultFn(() => new Date())
741
+ .$onUpdate(() => new Date()),
742
+ });
743
+ /**
744
+ * API keys (Go Prod §3.2, §3.3): `eo_live_<prefix>_<secret>` / `eo_test_…`. The prefix is the lookup
745
+ * (PK), the sha256 of the whole key the proof — the key itself is shown once and never stored.
746
+ * Revoked rows stay a year for the audit trail. Rotation (§3.3) sets the old key's `revokedAt` in
747
+ * the FUTURE (up to 30 days), so auth admits a key while `revokedAt IS NULL OR revokedAt > now`.
748
+ */
749
+ export const apiKeys = sqliteTable("api_keys", {
750
+ /** The 8-char prefix — unique, the lookup, and what the masked form shows. */
751
+ prefix: text().primaryKey(),
752
+ /** Lowercase hex sha256 of the full key string. */
753
+ keyHash: text().notNull(),
754
+ sourceId: text().notNull(),
755
+ /** A label for the Keys page. */
756
+ name: text(),
757
+ /** `eo_live_` (mainnet) or `eo_test_` (the testnet sandbox, §3.2). */
758
+ environment: text({ enum: ["live", "test"] }).notNull(),
759
+ scopes: text({ mode: "json" })
760
+ .$type()
761
+ .notNull(),
762
+ /** Daily spend cap, whole cents (§4.1 `402 SPEND_CAP`); null = no cap beyond the delegation's. */
763
+ maxSpendCentsPerDay: integer(),
764
+ /** Who created it (a member's `did:ixo`, or the operator). */
765
+ createdBy: text(),
766
+ lastUsedAt: integer({ mode: "timestamp_ms" }),
767
+ revokedAt: integer({ mode: "timestamp_ms" }),
768
+ createdAt: integer({ mode: "timestamp_ms" })
769
+ .notNull()
770
+ .$defaultFn(() => new Date()),
771
+ }, (t) => [index("api_keys_source_idx").on(t.sourceId)]);
772
+ /**
773
+ * People on a source (Go Prod §3.2): an IXO account, a role, and the `did:key` their review answers
774
+ * are signed with (§10). Invited by email, bound to a DID on accept — so `did` is null until then.
775
+ * One DID once per source (the unique index; SQLite admits many NULLs). Removed on request.
776
+ *
777
+ * A role is a UCAN delegation (§3.4, contracts v1.1): the owner signs, in their browser, a grant of
778
+ * the role's preset (`ROLE_CAPABILITIES`) over the source's resource to the member's DID, and the
779
+ * row keeps it (`delegation` + `delegationCid`) with what it says (`nbProtocols`, `expiresAt`) so
780
+ * a check needs no CAR parse. `role` is the preset's label, nothing more. The owner row is the root
781
+ * and carries no grant. A member without a stored grant can call nothing. Revoking stamps
782
+ * `revokedAt` AND lists the CID in `api_revocations`; a role change is a revoke plus a new grant.
783
+ */
784
+ export const apiMembers = sqliteTable("api_members", {
785
+ /** `mem_<ULID>`. */
786
+ memberId: text().primaryKey(),
787
+ sourceId: text().notNull(),
788
+ /** The member's `did:ixo` (AuthHub); null while the invite is open. */
789
+ did: text(),
790
+ email: text(),
791
+ role: text({ enum: ["owner", "developer", "reviewer", "viewer", "submitter"] }).notNull(),
792
+ /** The owner's signed grant, base64 of the delegation CAR; null until uploaded (and for the owner). */
793
+ delegation: text(),
794
+ /** The grant's CID — what a revocation lists and what `api_revocations` is checked against. */
795
+ delegationCid: text(),
796
+ /** The grant's `nb.protocols`: the protocols its `claims/*` are narrowed to; null = all. */
797
+ nbProtocols: text({ mode: "json" }).$type(),
798
+ /** The grant's expiry, in ms — a UCAN `exp` is in SECONDS, so `exp * 1000`; null = none. */
799
+ expiresAt: integer({ mode: "timestamp_ms" }),
800
+ revokedAt: integer({ mode: "timestamp_ms" }),
801
+ /**
802
+ * Lowercase hex sha256 of an email invite's one-time `inviteToken` (shown once, never stored);
803
+ * cleared on accept. Unique, so accept is one indexed lookup.
804
+ */
805
+ inviteTokenHash: text(),
806
+ /**
807
+ * When the email invite (`inviteTokenHash`) stops working — 7 days after it was sent (§3.4
808
+ * step 2); null for a member invited by DID, and once accepted.
809
+ */
810
+ inviteExpiresAt: integer({ mode: "timestamp_ms" }),
811
+ /** The Ed25519 `did:key` generated in their browser; a review answer's issuer must be one of these. */
812
+ reviewerDid: text(),
813
+ /**
814
+ * The member's own link to `reviewerDid` (company authority D2, F1): base64 CAR of the member
815
+ * did:ixo → reviewer did:key `claims/review` delegation, signed by the member — the middle of the
816
+ * chain the engine walks to name the member on the fold's receipt. Null until signed.
817
+ */
818
+ reviewerDelegation: text(),
819
+ /** That delegation's expiry, in ms (`exp * 1000`); null = none or none uploaded. */
820
+ reviewerDelegationExpiresAt: integer({ mode: "timestamp_ms" }),
821
+ /** The member's own switch for review emails (§10.1); Matrix follows the room's mute instead. */
822
+ notifyReviews: integer({ mode: "boolean" }).notNull().default(true),
823
+ /**
824
+ * When this member was last sent a review email for this source — the 15-minute window
825
+ * (§10.1, member-emails §6) opens here, and claims arriving inside it are held for one batch
826
+ * (lib/api-lane/reviewers.ts). Claimed by a conditional UPDATE, so two racing notify steps
827
+ * never both send.
828
+ */
829
+ reviewEmailAt: integer({ mode: "timestamp_ms" }),
830
+ invitedBy: text(),
831
+ invitedAt: integer({ mode: "timestamp_ms" })
832
+ .notNull()
833
+ .$defaultFn(() => new Date()),
834
+ acceptedAt: integer({ mode: "timestamp_ms" }),
835
+ }, (t) => [
836
+ uniqueIndex("api_members_source_did_idx").on(t.sourceId, t.did),
837
+ // The console's role lookup at sign-in: every source a DID belongs to.
838
+ index("api_members_did_idx").on(t.did),
839
+ // The review gate (§10.2): is this `did:key` a reviewer key of a member of THIS source? One
840
+ // key per member — registering from a second browser replaces it.
841
+ uniqueIndex("api_members_source_reviewer_idx").on(t.sourceId, t.reviewerDid),
842
+ uniqueIndex("api_members_invite_token_idx").on(t.inviteTokenHash),
843
+ ]);
844
+ /**
845
+ * A source's revocation list (§3.4): the CIDs of member grants the owner has withdrawn. Revoking
846
+ * adds the CID here and it is effective at once — every grant check reads this list, so a copy of
847
+ * the CAR still held by a browser (or re-uploaded) proves nothing. A grant REPLACED by a new one (a
848
+ * role change is a revoke plus a new grant) lands here too. Rows are never deleted: a CID is
849
+ * revoked for life. The PK is the lookup and the added-once mutex.
850
+ */
851
+ export const apiRevocations = sqliteTable("api_revocations", {
852
+ sourceId: text().notNull(),
853
+ cid: text().notNull(),
854
+ /** The member's `did:ixo` who revoked it, or the operator. */
855
+ revokedBy: text(),
856
+ revokedAt: integer({ mode: "timestamp_ms" })
857
+ .notNull()
858
+ .$defaultFn(() => new Date()),
859
+ }, (t) => [primaryKey({ columns: [t.sourceId, t.cid] })]);
860
+ /**
861
+ * An API claim's body and envelope (Go Prod §6.1, §6.2) — the D1 store the `api` `ClaimSource` pulls
862
+ * from. `body` is the canonical JSON of the answers; `bodyDigest` its sha256, checked on every pull
863
+ * (a mismatch fails closed, never a retry). Erasure nulls `body` (and `attachments`, `submitter`,
864
+ * `metadata`, `webhookUrl`, `content` — the personal data of §6.3), the claim's webhook rows' `payload` and
865
+ * `targetUrl`, deletes its `api_uploads` objects, and stamps `bodyErasedAt`; the row, the digests
866
+ * and the decision survive. Written in the SAME `db.batch` as the `claim_ingests` row and the
867
+ * `api_charges` row at accept (§4.6).
868
+ */
869
+ export const apiClaims = sqliteTable("api_claims", {
870
+ /** `apc_…` — also the `claim_ingests` / `decisions` key. */
871
+ claimId: text().primaryKey(),
872
+ sourceId: text().notNull(),
873
+ protocolDid: text().notNull(),
874
+ /** Canonical JSON of `answers`; null once erased. */
875
+ body: text({ mode: "json" }).$type(),
876
+ /** sha256 hex of the canonical body — the pull's integrity check; survives erasure. */
877
+ bodyDigest: text().notNull(),
878
+ /** The request's attachment descriptors (question, name, mediaType, url, cid) — never bytes. */
879
+ attachments: text({ mode: "json" }).$type(),
880
+ /** The org's end-user id, for display; personal data, so erased. */
881
+ submitter: text(),
882
+ /**
883
+ * HMAC-SHA256 (`UNIQUE_HMAC_KEY`) of `sourceId|submitter` — the frequency counter's key (§9),
884
+ * and why it is not `submitter` itself: it SURVIVES erasure, so a claim erased early still
885
+ * counts in its window. Null without a submitter ⇒ the fact is `unresolved`.
886
+ */
887
+ submitterDigest: text(),
888
+ /** Echoed on every webhook and GET, never evaluated (≤ 4 KB). */
889
+ metadata: text({ mode: "json" }).$type(),
890
+ idempotencyKey: text(),
891
+ /**
892
+ * sha256 of the whole canonical request — what a repeat of the same `Idempotency-Key` is
893
+ * compared against (`409 IDEMPOTENCY_MISMATCH`, §4.1). Null without a key.
894
+ */
895
+ requestDigest: text(),
896
+ webhookUrl: text(),
897
+ /**
898
+ * How the claim came in when not by an API key or the console: `oauth:<client_id>` for an AI
899
+ * app connected to `/v1/mcp` over OAuth (S7). Stamped on its `accepted` event; null otherwise.
900
+ */
901
+ via: text(),
902
+ /** The x402 offer to pay IF approved (§11.10). UNUSED at GA (contracts v1.1: no decision-to-pay,
903
+ * a submit carries no `payment`); always null, kept so the feature can return without a migration. */
904
+ payment: text({ mode: "json" }).$type(),
905
+ receivedAt: integer({ mode: "timestamp_ms" })
906
+ .notNull()
907
+ .$defaultFn(() => new Date()),
908
+ /** When the organisation erased the body (`DELETE /v1/api/claims/:claimId/body`) — never on a clock. */
909
+ bodyErasedAt: integer({ mode: "timestamp_ms" }),
910
+ /**
911
+ * `contentDigest(content)` (lib/hash.ts, `sha256:<hex>`) — the claim's content id, which the
912
+ * receipt carries and the SDK recomputes from what the app sent (company authority D3, A8).
913
+ * Survives erasure, like `bodyDigest`. Null for a claim accepted before contracts v1.7.
914
+ */
915
+ contentDigest: text(),
916
+ /**
917
+ * The claim CONTENT exactly as digested (`ApiClaimContent`): the submit body minus transport,
918
+ * with the resolved `protocolDid`, the caller's explicit `submitter` only and the attachments
919
+ * as SENT (before media-type detection rewrites `attachments` above). Kept apart from `body` so
920
+ * the engine can recompute the digest; it holds the answers, so it is erased with them.
921
+ */
922
+ content: text({ mode: "json" }).$type(),
923
+ /** Who SENT the claim, set server-side from the caller, never from the content: the OAuth
924
+ * user's DID (hosted MCP); null for an API key or a console submit, and before contracts v1.7.
925
+ * Not who the claim is about — that is `submitter`. */
926
+ submittedBy: text(),
927
+ /** WHICH AI app sent it (contracts v1.12.0 `submittedVia.name`): the OAuth client's registered
928
+ * name (`caller.clientName`, the AuthHub token's `client_name`), trimmed, ≤ 100 chars; null
929
+ * for an API key, a console submit and a chain claim. Self-declared at dynamic client
930
+ * registration, so a display hint for the console — never an authorisation input. */
931
+ submittedVia: text(),
932
+ /** The token's `verified` at submit (`submittedVia.verified`): AuthHub saw only Claude's or
933
+ * ChatGPT's own callback registered, so the token can only be theirs. Null iff
934
+ * `submittedVia` is. */
935
+ submittedViaVerified: integer({ mode: "boolean" }),
936
+ }, (t) => [
937
+ // The list route's keyset (`GET /v1/api/claims`): one source, newest first.
938
+ index("api_claims_source_received_idx").on(t.sourceId, t.receivedAt, t.claimId),
939
+ // The frequency counter (§9): one D1 count per (source, protocol, submitter, window).
940
+ index("api_claims_frequency_idx").on(t.sourceId, t.protocolDid, t.submitterDigest, t.receivedAt),
941
+ ]);
942
+ /**
943
+ * The oracle's pointer to each claim's payment (Go Prod §6.1, §11.3; payments spec §4, §13.4). The
944
+ * facilitator's reservations and settlements are the financial record; this row is for the timeline,
945
+ * support, the reconcile cron and the per-key cap. One row per accepted claim — `claimId` is the
946
+ * charged-once mutex. No refunds (nothing moves without a receipt, payments spec §0 rule 1).
947
+ *
948
+ * Lifecycle (contracts v1.3, standard x402): the row lands `reserved` in the accept batch, AFTER
949
+ * `/verify` reserved the price (the claim starts only then); after the decision row, `/settle` with
950
+ * the engine's receipt answers `settlement_pending` ⇒ `settled` (the receipt is accepted, the
951
+ * minute's transfer has not paid it yet) or `success` ⇒ `paid` with `txHash`; `reservation_released`
952
+ * ⇒ `released` (24 h without a receipt: nothing moved); any other refusal ⇒ `failed`, never retried.
953
+ * The reconcile re-settles `reserved`/`settled` rows of decided claims with the identical body until
954
+ * `paid`, and marks `released` a reservation past the facilitator's 24 h with no receipt — which a
955
+ * late settle the facilitator still accepts overwrites (`reservation_expired_late`). `settlementId` is the facilitator's, one per offer, so a batch's claims share it; `amount`
956
+ * is always THIS claim's price.
957
+ */
958
+ export const apiCharges = sqliteTable("api_charges", {
959
+ claimId: text().primaryKey(),
960
+ sourceId: text().notNull(),
961
+ /** The facilitator's settlement id (`org.udid.receipt@1` `settlementId`, 64 hex); null until settled. */
962
+ settlementId: text(),
963
+ /** Base units of `asset`, as a string (`"1200000"` = 1.20 PAY). */
964
+ amount: text().notNull(),
965
+ asset: text().notNull().default("upay"),
966
+ /** The facilitator offer (the 402's single-use nonce). */
967
+ offerId: text(),
968
+ /** The account at the root of the payment delegation — who was charged. */
969
+ payerDid: text(),
970
+ /** The API key that submitted — what the per-key daily cap (`402 SPEND_CAP`, §4.1) sums over. */
971
+ keyPrefix: text(),
972
+ /**
973
+ * `oauth:<grant id>` for a claim an AI app submitted over OAuth (S7) — what the per-grant daily
974
+ * cap sums over, as `keyPrefix` is for a key; null for a key or a console submit.
975
+ */
976
+ via: text(),
977
+ /** `amount` in whole USD cents (1 PAY = 1 USD), so the cap sums integers, never casts upay strings. */
978
+ amountCents: integer().notNull(),
979
+ /** TEXT with a type-only enum: adding a value needs no migration. */
980
+ status: text({
981
+ enum: [
982
+ // A chain claim's offer registered, its `/verify` not answered yet (review-billing.ts): a
983
+ // retry re-verifies the stored header, never re-offers. Never on an API claim.
984
+ "offered",
985
+ "reserved",
986
+ "settled",
987
+ "paid",
988
+ "released",
989
+ "failed",
990
+ // Card only (PAY's transfer is final): the facilitator's refund, read there (refund.ts).
991
+ "refunded",
992
+ "partially_refunded",
993
+ ],
994
+ })
995
+ .notNull()
996
+ .default("reserved"),
997
+ /** The transfer that paid it (`/settle`'s `transaction`, a chain tx hash) — only ever real. */
998
+ txHash: text(),
999
+ /** The facilitator's last `/settle` answer, verbatim: a sync 200's `PAYMENT-RESPONSE`. A
1000
+ * pre-v1.3 hold keeps its old id here instead (`{ legacyChargeId }`). */
1001
+ settleResult: text({ mode: "json" }).$type(),
1002
+ /** The verified `PAYMENT-SIGNATURE` every `/settle` of this claim is built from (identical on
1003
+ * every retry), SEALED (`v1:`, payments/header-seal.ts — it embeds the payer's reusable
1004
+ * payment delegation); KV holds a second copy. Null for rows written before contracts v1.3;
1005
+ * in the clear on rows written before 2026-10-14, until the housekeeping sweep seals them. */
1006
+ paymentHeader: text(),
1007
+ /** What the header pays with (`ixo-pay` | `stripe-manual-capture` | `exact`), in the clear so
1008
+ * a claim read never decrypts. Null on rows the sweep has not reached (read off a clear header). */
1009
+ scheme: text({ enum: ["ixo-pay", "stripe-manual-capture", "exact"] }),
1010
+ /**
1011
+ * Per-review checker billing: `chain` for a CHAIN claim's charge (the claim id is the chain's,
1012
+ * `collectionId` its collection) — the two fields the facilitator keys the reservation by
1013
+ * besides the claim (x402-ixo-pay 0.7.0). Null = an API decision.
1014
+ */
1015
+ lane: text({ enum: ["chain"] }),
1016
+ collectionId: text(),
1017
+ /**
1018
+ * When the facilitator will release the reservation, once a `pending_review` claim's hold was
1019
+ * extended for its human review (`POST /v1/reservations/extend`, payments/extend.ts); null =
1020
+ * the default 24 h from `createdAt`. What the reconcile's expiry arm and a review's deadline read.
1021
+ */
1022
+ reservationExpiresAt: integer({ mode: "timestamp_ms" }),
1023
+ /**
1024
+ * A card payment's refund, as the facilitator reports it (`GET /v1/card/refunds/:claimId`,
1025
+ * payments/refund.ts) — never on the console's word. Null for PAY and an unrefunded card.
1026
+ */
1027
+ refundedAt: integer({ mode: "timestamp_ms" }),
1028
+ refundId: text(),
1029
+ refundedAmountCents: integer(),
1030
+ /** When the reconcile last asked the facilitator about this card charge's refund (its turn). */
1031
+ refundCheckedAt: integer({ mode: "timestamp_ms" }),
1032
+ error: text(),
1033
+ createdAt: integer({ mode: "timestamp_ms" })
1034
+ .notNull()
1035
+ .$defaultFn(() => new Date()),
1036
+ updatedAt: integer({ mode: "timestamp_ms" })
1037
+ .notNull()
1038
+ .$defaultFn(() => new Date())
1039
+ .$onUpdate(() => new Date()),
1040
+ }, (t) => [
1041
+ index("api_charges_settlement_idx").on(t.settlementId),
1042
+ // The reconcile: open rows by status, the least recently tried first.
1043
+ index("api_charges_status_updated_idx").on(t.status, t.updatedAt),
1044
+ // The Spend page: one source's charges by day.
1045
+ index("api_charges_source_created_idx").on(t.sourceId, t.createdAt),
1046
+ // The per-key daily cap: today's charges of one key.
1047
+ index("api_charges_key_created_idx").on(t.keyPrefix, t.createdAt),
1048
+ // The per-grant daily cap (S7): today's charges of one OAuth grant.
1049
+ index("api_charges_via_created_idx").on(t.via, t.createdAt),
1050
+ // The daily reconciliation (one day across every source) and the retention trim.
1051
+ index("api_charges_created_idx").on(t.createdAt),
1052
+ ]);
1053
+ /**
1054
+ * A source's standing review-billing delegation (per-review checker billing,
1055
+ * active by IXO's plan for the oracle; payments/review-billing.ts): the x402-ixo-pay payment delegation its
1056
+ * organisation's chain OWNER signed — one `billing/pay` to the facilitator, bound to this oracle
1057
+ * alone (`nb.oracles`) — that pays for every chain claim of the organisation's collections. One
1058
+ * row per source, and one source per organisation holding a live one (the PUT route enforces it).
1059
+ *
1060
+ * `delegationCiphertext` is a bearer credential: sealed (`v1:`, webhook-crypto.ts), never logged,
1061
+ * never returned, never a step result. `spentUpay` is this oracle's mirror of what the facilitator
1062
+ * counts against the delegation's `maxAmount` (it exposes no read): raised by ONE conditional
1063
+ * statement per reservation (`spentUpay + price ≤ capUpay`), given back only when `/verify` reserved
1064
+ * nothing — a lapsed reservation keeps counting, as the facilitator's does. With `nb.oracles` =
1065
+ * [this oracle] nobody else can spend the CID, so the mirror is exact. A new CID starts at 0, as
1066
+ * the facilitator's per-CID count does. `capUpay` is `maxAmount` capped to a safe integer (the
1067
+ * comparison is SQL), `maxAmount` the exact string. Deleted with the source, and 30 days past
1068
+ * `expiresAt` by the housekeeping sweep.
1069
+ */
1070
+ export const reviewBillingDelegations = sqliteTable("review_billing_delegations", {
1071
+ sourceId: text().primaryKey(),
1072
+ /** The delegation's issuer — the organisation's chain owner when stored; who pays. */
1073
+ payerDid: text().notNull(),
1074
+ delegationCid: text().notNull(),
1075
+ /** `nb.maxAmount`, upay base units, exact. */
1076
+ maxAmount: text().notNull(),
1077
+ capUpay: integer().notNull(),
1078
+ spentUpay: integer().notNull().default(0),
1079
+ expiresAt: integer({ mode: "timestamp_ms" }).notNull(),
1080
+ notBefore: integer({ mode: "timestamp_ms" }),
1081
+ delegationCiphertext: text().notNull(),
1082
+ /** The member who stored it (`keys/manage` or a controller) — not necessarily the payer. */
1083
+ createdBy: text().notNull(),
1084
+ createdAt: integer({ mode: "timestamp_ms" })
1085
+ .notNull()
1086
+ .$defaultFn(() => new Date()),
1087
+ updatedAt: integer({ mode: "timestamp_ms" })
1088
+ .notNull()
1089
+ .$defaultFn(() => new Date())
1090
+ .$onUpdate(() => new Date()),
1091
+ }, (t) => [
1092
+ // The expiry reminders and the housekeeping sweep: rows by expiry.
1093
+ index("review_billing_delegations_expires_idx").on(t.expiresAt),
1094
+ ]);
1095
+ /**
1096
+ * The per-claim timeline (`GET /v1/api/claims/:claimId/events`, Go Prod §4.2): accepted, paid, facts
1097
+ * produced (names and durations, NEVER values), decided, webhook attempts, review answered, folded,
1098
+ * erased. Append-only, one statement per event; source-level events carry a null `claimId`. Kept a
1099
+ * year (the retention cron trims). The claim index is not source-scoped: a timeline read proves the
1100
+ * claim is the caller's through `api_claims` first (404 otherwise, §14).
1101
+ */
1102
+ export const apiEvents = sqliteTable("api_events", {
1103
+ /** `evt_<ULID>` — sortable, so the timeline orders by id. */
1104
+ eventId: text().primaryKey(),
1105
+ sourceId: text().notNull(),
1106
+ claimId: text(),
1107
+ type: text().notNull(),
1108
+ /** Small, log-safe detail: fact names + durations, a status code, the engine's issues. Never an answer. */
1109
+ data: text({ mode: "json" }).$type(),
1110
+ createdAt: integer({ mode: "timestamp_ms" })
1111
+ .notNull()
1112
+ .$defaultFn(() => new Date()),
1113
+ }, (t) => [
1114
+ index("api_events_claim_idx").on(t.claimId, t.eventId),
1115
+ index("api_events_source_created_idx").on(t.sourceId, t.createdAt),
1116
+ index("api_events_created_idx").on(t.createdAt),
1117
+ ]);
1118
+ /** Every portal, CLI and operator action on a source — who, what, when (Go Prod §6.1; kept 2 years). */
1119
+ export const apiAudit = sqliteTable("api_audit", {
1120
+ /** `aud_<ULID>`. */
1121
+ auditId: text().primaryKey(),
1122
+ /** Null for an operator action not tied to one source. */
1123
+ sourceId: text(),
1124
+ /** Who acted — a member or operator DID, or the API key's prefix. */
1125
+ actor: text().notNull(),
1126
+ /** What `actor` is, so the audit log can show it without guessing from the string. */
1127
+ /**
1128
+ * `system` is the oracle acting on its own schedule (a cron); its `actor` is then
1129
+ * `system:<job>`, e.g. `system:link-recheck`. `oauth` is a user acting through an AI app over
1130
+ * OAuth (S7). TEXT with a type-only enum: a new kind is no migration.
1131
+ */
1132
+ actorKind: text({ enum: ["member", "key", "operator", "system", "oauth"] }).notNull(),
1133
+ /**
1134
+ * For `actorKind: oauth` (S7) — the user's `did:ixo` is `actor`, and these name the AI app
1135
+ * acting for them, as AuthHub registered it. Null for every other kind.
1136
+ */
1137
+ clientId: text(),
1138
+ clientName: text(),
1139
+ /** `key.created`, `key.revoked`, `member.invited`, `claim.erased`, `source.paused`, … */
1140
+ action: text().notNull(),
1141
+ /** What it acted on (a key prefix, a member id, a claim id). */
1142
+ target: text(),
1143
+ details: text({ mode: "json" }).$type(),
1144
+ requestId: text(),
1145
+ createdAt: integer({ mode: "timestamp_ms" })
1146
+ .notNull()
1147
+ .$defaultFn(() => new Date()),
1148
+ }, (t) => [
1149
+ index("api_audit_source_created_idx").on(t.sourceId, t.createdAt),
1150
+ index("api_audit_created_idx").on(t.createdAt),
1151
+ ]);
1152
+ /**
1153
+ * A source's webhook endpoints (Go Prod §4.5). The signing secret is stored ENCRYPTED with the
1154
+ * deployment's `WEBHOOK_ENCRYPTION_KEY` (§6.1) — it must be recoverable to sign, so a hash will not
1155
+ * do. `events` empty = every event. Deliveries are `matrix_deliveries` rows of `kind: "webhook"`.
1156
+ */
1157
+ export const webhookEndpoints = sqliteTable("webhook_endpoints", {
1158
+ /** `whe_<ULID>`. */
1159
+ endpointId: text().primaryKey(),
1160
+ sourceId: text().notNull(),
1161
+ url: text().notNull(),
1162
+ /**
1163
+ * The HMAC secret, encrypted at rest; returned in clear once, on create or rotate. Prefixed
1164
+ * with the key version (`v1:<ciphertext>`) so `WEBHOOK_ENCRYPTION_KEY` can be rotated (§14's
1165
+ * compromise runbook) by re-encrypting row by row.
1166
+ */
1167
+ secretCiphertext: text().notNull(),
1168
+ /**
1169
+ * The secret a rotation replaced, still signing beside the new one until
1170
+ * `previousSecretExpiresAt` (24 h) — the signature header then carries one `v1=` per live
1171
+ * secret, so a receiver can swap without dropping events.
1172
+ */
1173
+ previousSecretCiphertext: text(),
1174
+ previousSecretExpiresAt: integer({ mode: "timestamp_ms" }),
1175
+ events: text({ mode: "json" }).$type().notNull().default([]),
1176
+ status: text({ enum: ["active", "disabled"] })
1177
+ .notNull()
1178
+ .default("active"),
1179
+ description: text(),
1180
+ createdAt: integer({ mode: "timestamp_ms" })
1181
+ .notNull()
1182
+ .$defaultFn(() => new Date()),
1183
+ updatedAt: integer({ mode: "timestamp_ms" })
1184
+ .notNull()
1185
+ .$defaultFn(() => new Date())
1186
+ .$onUpdate(() => new Date()),
1187
+ }, (t) => [index("webhook_endpoints_source_idx").on(t.sourceId)]);
1188
+ /**
1189
+ * The idempotency store for every POST/PUT that is not a claim submit (Go Prod §4.1): same key +
1190
+ * same request ⇒ the stored answer for 24 h; same key + a different request ⇒ `409
1191
+ * IDEMPOTENCY_MISMATCH`. The INSERT with `onConflictDoNothing` is the in-flight mutex (`status:
1192
+ * in_flight` until the answer lands). A claim submit does not use it: its `claimId` is derived from
1193
+ * the key, so the `claim_ingests` PK is the guard and `api_claims.requestDigest` the mismatch check
1194
+ * — and a repeat answers the claim's CURRENT state, not a stored response (§4.6).
1195
+ *
1196
+ * An `in_flight` row older than 60 s is a request that died: the next attempt reclaims it with one
1197
+ * conditional upsert (`onConflictDoUpdate … where status = 'in_flight' and created_at < now - 60s`),
1198
+ * so a crash never locks a key for the day. A response carrying a one-time secret (a new API key,
1199
+ * a webhook secret) is stored WITHOUT it — the secret field replaced by null — since keys live only
1200
+ * as hashes and secrets only encrypted (§3.2, §6.1); the replay says so, and the caller rotates.
1201
+ */
1202
+ export const apiIdempotency = sqliteTable("api_idempotency", {
1203
+ sourceId: text().notNull(),
1204
+ idempotencyKey: text().notNull(),
1205
+ /** sha256 of method + path + canonical body. */
1206
+ requestDigest: text().notNull(),
1207
+ status: text({ enum: ["in_flight", "done"] })
1208
+ .notNull()
1209
+ .default("in_flight"),
1210
+ responseStatus: integer(),
1211
+ responseBody: text({ mode: "json" }).$type(),
1212
+ createdAt: integer({ mode: "timestamp_ms" })
1213
+ .notNull()
1214
+ .$defaultFn(() => new Date()),
1215
+ /** createdAt + 24 h; the retention cron deletes past it. */
1216
+ expiresAt: integer({ mode: "timestamp_ms" }).notNull(),
1217
+ }, (t) => [
1218
+ primaryKey({ columns: [t.sourceId, t.idempotencyKey] }),
1219
+ index("api_idempotency_expires_idx").on(t.expiresAt),
1220
+ ]);
1221
+ /**
1222
+ * Files uploaded through `PUT /v1/api/uploads` (Go Prod §6.2), and the export bundles: the R2
1223
+ * object's pointer, so an erase or the housekeeping sweep can find every object without reading
1224
+ * erasable claim columns. `claimId` is bound when a submit references the upload, and the claim's
1225
+ * erase deletes it. `deleteAt` is set only by an organisation's own action — an export bundle's one
1226
+ * day, a deleted source's files — and the hourly sweep then deletes the object and the row; null =
1227
+ * kept (the oracle never deletes an organisation's files on its own).
1228
+ */
1229
+ export const apiUploads = sqliteTable("api_uploads", {
1230
+ /** `upl_<ULID>`. */
1231
+ uploadId: text().primaryKey(),
1232
+ sourceId: text().notNull(),
1233
+ /** `uploads/<sourceId>/<ULID>` in `API_UPLOADS`. */
1234
+ r2Key: text().notNull(),
1235
+ cid: text().notNull(),
1236
+ mediaType: text().notNull(),
1237
+ size: integer().notNull(),
1238
+ claimId: text(),
1239
+ deleteAt: integer({ mode: "timestamp_ms" }),
1240
+ createdAt: integer({ mode: "timestamp_ms" })
1241
+ .notNull()
1242
+ .$defaultFn(() => new Date()),
1243
+ }, (t) => [
1244
+ index("api_uploads_delete_idx").on(t.deleteAt),
1245
+ index("api_uploads_claim_idx").on(t.claimId),
1246
+ ]);
1247
+ /**
1248
+ * On-chain collections an organisation (a source) has linked, so its claim reads include that
1249
+ * collection's CHAIN claims (Go Prod S3 M6). Linked by a console member who is, ON CHAIN, the
1250
+ * collection entity's owner (company authority D9); the hourly re-check
1251
+ * (`lib/api-lane/linked.ts`) drops a link whose linker no longer owns it — the link
1252
+ * rides on that one member's standing, never the source's. Billing for these claims stays the
1253
+ * collection owner's on-chain evaluation payment: nothing is charged at the oracle.
1254
+ *
1255
+ * The same collection may be linked to several sources (PK `(sourceId, collectionId)`); the
1256
+ * `collectionId` index serves "which sources see this collection". `checkedAt` rotates the
1257
+ * re-check: least recently checked first, every link each hour up to a hard cap. `verifiedAt` is
1258
+ * the last check that CONFIRMED the linker's standing — a record for operators, never a read
1259
+ * filter: a link is shown while the row exists, and only the re-check's POSITIVE finding deletes it
1260
+ * (lib/api-lane/linked.ts header). An unreadable chain or engine keeps it.
1261
+ */
1262
+ export const apiSourceCollections = sqliteTable("api_source_collections", {
1263
+ sourceId: text().notNull(),
1264
+ collectionId: text().notNull(),
1265
+ /** The collection's protocol, read off the chain at link time. */
1266
+ protocolDid: text().notNull(),
1267
+ /** The member's `did:ixo` — whose standing the re-check verifies. */
1268
+ linkedBy: text().notNull(),
1269
+ linkedAt: integer({ mode: "timestamp_ms" })
1270
+ .notNull()
1271
+ .$defaultFn(() => new Date()),
1272
+ checkedAt: integer({ mode: "timestamp_ms" })
1273
+ .notNull()
1274
+ .$defaultFn(() => new Date()),
1275
+ /** The last check that confirmed the linker's standing (the link itself is the first). */
1276
+ verifiedAt: integer({ mode: "timestamp_ms" })
1277
+ .notNull()
1278
+ .$defaultFn(() => new Date()),
1279
+ /**
1280
+ * Consecutive re-checks that found no such collection on chain. One is not enough to unlink —
1281
+ * an indexer that lags or re-syncs answers "not found" for a while — so the link goes on the
1282
+ * second in a row; any confirmed check resets it.
1283
+ */
1284
+ missCount: integer().notNull().default(0),
1285
+ }, (t) => [
1286
+ primaryKey({ columns: [t.sourceId, t.collectionId] }),
1287
+ index("api_source_collections_collection_idx").on(t.collectionId),
1288
+ index("api_source_collections_checked_idx").on(t.checkedAt),
1289
+ ]);
1290
+ /**
1291
+ * One AI Gateway call per row (spec 2026-10-02 §6) — the `cloudflare` provider's spend, for
1292
+ * operators and admin apps only: nothing that decides or verifies reads it. Written once per build
1293
+ * by builder.ts (`onConflictDoNothing` on the gateway log id — a replayed write inserts nothing);
1294
+ * the USD lands later from the gateway's own log (cron/ai-cost.ts): `pending` → `ok`, or
1295
+ * `unavailable` (logging off, no price for the model, retention). OpenRouter calls are not here —
1296
+ * their cost is frozen on the FactSet at call time. Trimmed after 90 days by the same job.
1297
+ */
1298
+ export const aiCalls = sqliteTable("ai_calls", {
1299
+ /** The gateway log id (`cf-aig-log-id`). */
1300
+ callId: text().primaryKey(),
1301
+ claimId: text().notNull(),
1302
+ /** `<name>` of the ai check (or `<name>#n` for a handler's nth judge call), or `unique.judge`. */
1303
+ fact: text().notNull(),
1304
+ model: text().notNull(),
1305
+ promptTokens: integer(),
1306
+ completionTokens: integer(),
1307
+ cachedTokens: integer(),
1308
+ /** USD × 1e6 — integers, the money rule. Null until backfilled. */
1309
+ costMicroUsd: integer(),
1310
+ costStatus: text({ enum: ["pending", "ok", "unavailable"] })
1311
+ .notNull()
1312
+ .default("pending"),
1313
+ createdAt: integer({ mode: "timestamp_ms" })
1314
+ .notNull()
1315
+ .$defaultFn(() => new Date()),
1316
+ costAt: integer({ mode: "timestamp_ms" }),
1317
+ }, (t) => [
1318
+ index("ai_calls_pending_idx").on(t.costStatus, t.createdAt),
1319
+ index("ai_calls_claim_idx").on(t.claimId),
1320
+ ]);
1321
+ /**
1322
+ * One per-submit approval of an AI app's claim (MCP over OAuth, spec 2026-10-06; S7). An OAuth
1323
+ * caller's `submit_claim` never pays on the token alone: the first call files this row and answers
1324
+ * `APPROVAL_REQUIRED` with AuthHub's approve link; the user approves THERE (AuthHub reads the row
1325
+ * over the back-channel, `GET /v1/oauth/approvals/:id`, so the page shows the oracle's record, never
1326
+ * the model's words) and AuthHub posts back a one-claim payment delegation. The same request again
1327
+ * finds the row by `(grantId, requestDigest)` and spends it ONCE: a conditional UPDATE
1328
+ * (`approved` → `used`) claims it before anything is paid. A card that wants 3-D Secure parks it
1329
+ * as `awaiting_3ds`, bound to that offer and PaymentIntent, until the resume.
1330
+ *
1331
+ * `delegation` is a bearer credential: never logged, never returned (the GET back-channel omits
1332
+ * it), and NULL again the moment the row is used, declined or expired. The housekeeping sweep deletes
1333
+ * rows past `expiresAt`.
1334
+ */
1335
+ export const mcpApprovals = sqliteTable("mcp_approvals", {
1336
+ /** 128 random bits, base64url (22 chars) — the approve link's `id`. */
1337
+ id: text().primaryKey(),
1338
+ /** AuthHub's grant (`gid`) the token carried: an approval never moves to another app. */
1339
+ grantId: text().notNull(),
1340
+ /** The user (`sub`, a `did:ixo`) — the delegation's root issuer must be this. */
1341
+ did: text().notNull(),
1342
+ sourceId: text().notNull(),
1343
+ protocolDid: text().notNull(),
1344
+ clientId: text().notNull(),
1345
+ clientName: text().notNull(),
1346
+ /** sha256 over protocol, source, canonical body, attachments and the idempotency key. */
1347
+ requestDigest: text().notNull(),
1348
+ /** The price as the approve page shows it (`$1.20`, or `No charge`). */
1349
+ price: text().notNull(),
1350
+ /** What the delegation must cover, upay (1 PAY = 1 USD = 1 000 000 upay); `0` for `none`. */
1351
+ maxAmountUpay: text().notNull(),
1352
+ /** The source's billing mode when asked: `none` approves without a delegation. */
1353
+ billingMode: text({ enum: ["x402", "none"] }).notNull(),
1354
+ /** TEXT with a type-only enum. */
1355
+ status: text({ enum: ["pending", "approved", "awaiting_3ds", "used", "expired", "declined"] })
1356
+ .notNull()
1357
+ .default("pending"),
1358
+ /** The one-claim payment delegation (base64 CAR); null until approved, and once spent. */
1359
+ delegation: text(),
1360
+ /**
1361
+ * `awaiting_3ds` only: the card offer and PaymentIntent the bank asked to confirm. Only a resume
1362
+ * of exactly that offer, paid by exactly that PaymentIntent, may spend the row again.
1363
+ */
1364
+ offerId: text(),
1365
+ paymentIntentId: text(),
1366
+ /** 15 min after asking; reset to 15 min after approving, for the retry to use it. */
1367
+ expiresAt: integer({ mode: "timestamp_ms" }).notNull(),
1368
+ createdAt: integer({ mode: "timestamp_ms" })
1369
+ .notNull()
1370
+ .$defaultFn(() => new Date()),
1371
+ }, (t) => [
1372
+ // The retry's lookup, and the find-or-create's mutex: at most ONE live approval per app and
1373
+ // exact request, so two racing first calls file one row (`onConflictDoNothing`).
1374
+ uniqueIndex("mcp_approvals_live_idx")
1375
+ .on(t.grantId, t.requestDigest)
1376
+ .where(sql `status in ('pending', 'approved', 'awaiting_3ds')`),
1377
+ // The housekeeping sweep.
1378
+ index("mcp_approvals_expires_idx").on(t.expiresAt),
1379
+ ]);
1380
+ /**
1381
+ * A grant's auto-approve ("don't ask again", spec 2026-10-06 "Auto-approve"; S7): the standing
1382
+ * payment authority the user gave an AI app on AuthHub — up to `perClaimUpay` a claim and
1383
+ * `totalUpay` in all, until `until`. One row per AuthHub grant. `delegation` is a bearer credential
1384
+ * whose `maxAmount` IS `totalUpay` (the facilitator enforces the total too): never logged or
1385
+ * returned, deleted with the row. `spentUpay` is moved only by single conditional statements, so
1386
+ * concurrent submits can never take it past `totalUpay`. Amounts are upay INTEGERs (the total is at
1387
+ * most $100 = 1e8 upay, far inside SQLite's 64-bit range).
1388
+ */
1389
+ export const mcpStanding = sqliteTable("mcp_standing", {
1390
+ /** AuthHub's grant (`gid`). */
1391
+ grantId: text().primaryKey(),
1392
+ /** The user (`sub`): the delegation's root issuer. */
1393
+ did: text().notNull(),
1394
+ perClaimUpay: integer().notNull(),
1395
+ totalUpay: integer().notNull(),
1396
+ spentUpay: integer().notNull().default(0),
1397
+ until: integer({ mode: "timestamp_ms" }).notNull(),
1398
+ /** The standing payment delegation (base64 CAR), `maxAmount` = `totalUpay`. */
1399
+ delegation: text(),
1400
+ updatedAt: integer({ mode: "timestamp_ms" })
1401
+ .notNull()
1402
+ .$defaultFn(() => new Date())
1403
+ .$onUpdate(() => new Date()),
1404
+ });
1405
+ /**
1406
+ * A grant's ONE day counter and per-request lock (S3 reviews of #87 and #90). Three kinds of row,
1407
+ * all keyed (grant, key):
1408
+ * - an auto-approve spend (key = the request digest): written in the SAME `db.batch` as the
1409
+ * `mcp_standing` spend, which lands only if this row did — so a retry of the same request (a
1410
+ * model timeout, an ambiguous failure) never spends or pays again;
1411
+ * - a one-claim approval's spend (`approvalSpendKey`), written by `spendApproval`, whose flip
1412
+ * needs it — so the $20/day cap is atomic across both paths; a restore deletes it;
1413
+ * - an answer's marker (`answer:<approval id>`, 0 upay): the one AuthHub answer that won an
1414
+ * approval (`approveWithStanding`).
1415
+ * Each spend row is kept on any outcome but a proven-nothing-reserved refund or restore, which
1416
+ * deletes it in the same batch. `upay` is what the daily cap sums. The sweep trims old rows.
1417
+ */
1418
+ export const mcpStandingSpends = sqliteTable("mcp_standing_spends", {
1419
+ grantId: text().notNull(),
1420
+ /** The approval digest of the request (`approvalDigest`). */
1421
+ requestDigest: text().notNull(),
1422
+ /** Random per attempt: the spend's own claim on the row (its batch checks it is this one). */
1423
+ spendId: text().notNull(),
1424
+ upay: integer().notNull(),
1425
+ createdAt: integer({ mode: "timestamp_ms" })
1426
+ .notNull()
1427
+ .$defaultFn(() => new Date()),
1428
+ }, (t) => [
1429
+ primaryKey({ columns: [t.grantId, t.requestDigest] }),
1430
+ // The daily cap's sum, and the sweep.
1431
+ index("mcp_standing_spends_grant_created_idx").on(t.grantId, t.createdAt),
1432
+ ]);
1433
+ //# sourceMappingURL=schema.js.map