@dakkitor/api-contracts 1.1.154 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/dist/abilities/abilities.contract.d.ts +55 -1
  2. package/dist/abilities/abilities.contract.d.ts.map +1 -1
  3. package/dist/abilities/abilities.contract.js +95 -1
  4. package/dist/abilities/abilities.contract.spec.d.ts +2 -0
  5. package/dist/abilities/abilities.contract.spec.d.ts.map +1 -0
  6. package/dist/abilities/abilities.contract.spec.js +145 -0
  7. package/dist/abilities/admin-dashboard.abilities.test.d.ts +2 -0
  8. package/dist/abilities/admin-dashboard.abilities.test.d.ts.map +1 -0
  9. package/dist/abilities/admin-dashboard.abilities.test.js +33 -0
  10. package/dist/abilities/admin.abilities.json +19 -0
  11. package/dist/abilities/bot.abilities.json +13 -4
  12. package/dist/abilities/first-agent.abilities.json +330 -70
  13. package/dist/abilities/interconnection.abilities.json +75 -0
  14. package/dist/abilities/kpi.abilities.json +68 -0
  15. package/dist/abilities/office-manager.abilities.json +111 -0
  16. package/dist/abilities/outreach-service.abilities.json +14 -0
  17. package/dist/abilities/second-agent.abilities.json +430 -43
  18. package/dist/abilities/team-leads.json +71 -6
  19. package/dist/abilities/worker-curator.abilities.json +233 -0
  20. package/dist/actives/actives.contract.d.ts +15521 -19793
  21. package/dist/actives/actives.contract.d.ts.map +1 -1
  22. package/dist/actives/actives.contract.js +517 -114
  23. package/dist/agent-client-links/agent-client-links.contract.d.ts +1431 -291
  24. package/dist/agent-client-links/agent-client-links.contract.d.ts.map +1 -1
  25. package/dist/auth/auth.contract.d.ts +1050 -81
  26. package/dist/auth/auth.contract.d.ts.map +1 -1
  27. package/dist/auth/auth.contract.js +115 -3
  28. package/dist/bookings/booking-worker-summary.spec.d.ts +2 -0
  29. package/dist/bookings/booking-worker-summary.spec.d.ts.map +1 -0
  30. package/dist/bookings/booking-worker-summary.spec.js +25 -0
  31. package/dist/bookings/bookings.contract.d.ts +21631 -27105
  32. package/dist/bookings/bookings.contract.d.ts.map +1 -1
  33. package/dist/bookings/bookings.contract.js +383 -91
  34. package/dist/bookings/bookings.contract.spec.d.ts +2 -0
  35. package/dist/bookings/bookings.contract.spec.d.ts.map +1 -0
  36. package/dist/bookings/bookings.contract.spec.js +11 -0
  37. package/dist/bookings/job-lock.spec.d.ts +2 -0
  38. package/dist/bookings/job-lock.spec.d.ts.map +1 -0
  39. package/dist/bookings/job-lock.spec.js +56 -0
  40. package/dist/bot-parse-cache/bot-parse-cache.contract.d.ts +232 -0
  41. package/dist/bot-parse-cache/bot-parse-cache.contract.d.ts.map +1 -0
  42. package/dist/bot-parse-cache/bot-parse-cache.contract.js +64 -0
  43. package/dist/call-history/call-history.contract.d.ts +1336 -767
  44. package/dist/call-history/call-history.contract.d.ts.map +1 -1
  45. package/dist/call-history/call-history.contract.js +86 -10
  46. package/dist/calls-feed/calls-feed.contract.d.ts +417 -0
  47. package/dist/calls-feed/calls-feed.contract.d.ts.map +1 -0
  48. package/dist/calls-feed/calls-feed.contract.js +32 -0
  49. package/dist/client-contacts/client-contacts.contract.d.ts +410 -226
  50. package/dist/client-contacts/client-contacts.contract.d.ts.map +1 -1
  51. package/dist/client-contacts/client-contacts.contract.js +35 -4
  52. package/dist/clients/clients.contract.d.ts +227 -73
  53. package/dist/clients/clients.contract.d.ts.map +1 -1
  54. package/dist/clients/clients.contract.js +45 -21
  55. package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts +2908 -1834
  56. package/dist/collaboration-checkings/collaboration-checkings.contract.d.ts.map +1 -1
  57. package/dist/collaboration-checkings/collaboration-checkings.contract.js +14 -9
  58. package/dist/collaborations/collaborations.contract.d.ts +2676 -1409
  59. package/dist/collaborations/collaborations.contract.d.ts.map +1 -1
  60. package/dist/collaborations/collaborations.contract.js +33 -9
  61. package/dist/common/call-rating.schema.d.ts.map +1 -1
  62. package/dist/common/call-rating.schema.js +4 -2
  63. package/dist/common/common-schemas.d.ts +59 -11
  64. package/dist/common/common-schemas.d.ts.map +1 -1
  65. package/dist/common/common-schemas.js +55 -29
  66. package/dist/common/error-schemas.d.ts +2 -2
  67. package/dist/common/pagination-query.schema.d.ts +13 -2
  68. package/dist/common/pagination-query.schema.d.ts.map +1 -1
  69. package/dist/common/pagination-query.schema.js +21 -2
  70. package/dist/common/pagination-query.schema.spec.d.ts +2 -0
  71. package/dist/common/pagination-query.schema.spec.d.ts.map +1 -0
  72. package/dist/common/pagination-query.schema.spec.js +53 -0
  73. package/dist/companies/companies.contract.d.ts +53 -28
  74. package/dist/companies/companies.contract.d.ts.map +1 -1
  75. package/dist/companies/companies.contract.js +11 -10
  76. package/dist/crews/crews.contract.d.ts +1010 -196
  77. package/dist/crews/crews.contract.d.ts.map +1 -1
  78. package/dist/crews/crews.contract.js +98 -17
  79. package/dist/crews/crews.contract.spec.d.ts +2 -0
  80. package/dist/crews/crews.contract.spec.d.ts.map +1 -0
  81. package/dist/crews/crews.contract.spec.js +67 -0
  82. package/dist/cron-executions/cron-executions.contract.d.ts +988 -59
  83. package/dist/cron-executions/cron-executions.contract.d.ts.map +1 -1
  84. package/dist/cron-executions/cron-executions.contract.js +127 -7
  85. package/dist/curated-worker-leads/__tests__/disposition-reason.spec.d.ts +2 -0
  86. package/dist/curated-worker-leads/__tests__/disposition-reason.spec.d.ts.map +1 -0
  87. package/dist/curated-worker-leads/__tests__/disposition-reason.spec.js +40 -0
  88. package/dist/curated-worker-leads/candidate-coordination-snapshot.spec.d.ts +2 -0
  89. package/dist/curated-worker-leads/candidate-coordination-snapshot.spec.d.ts.map +1 -0
  90. package/dist/curated-worker-leads/candidate-coordination-snapshot.spec.js +16 -0
  91. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts +21650 -0
  92. package/dist/curated-worker-leads/candidate-coordination.contract.d.ts.map +1 -0
  93. package/dist/curated-worker-leads/candidate-coordination.contract.js +921 -0
  94. package/dist/curated-worker-leads/candidate-coordination.contract.spec.d.ts +2 -0
  95. package/dist/curated-worker-leads/candidate-coordination.contract.spec.d.ts.map +1 -0
  96. package/dist/curated-worker-leads/candidate-coordination.contract.spec.js +51 -0
  97. package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts +2364 -0
  98. package/dist/curated-worker-leads/candidate-edit-session.contract.d.ts.map +1 -0
  99. package/dist/curated-worker-leads/candidate-edit-session.contract.js +173 -0
  100. package/dist/curated-worker-leads/consent-queue.contract.d.ts +4497 -0
  101. package/dist/curated-worker-leads/consent-queue.contract.d.ts.map +1 -0
  102. package/dist/curated-worker-leads/consent-queue.contract.js +201 -0
  103. package/dist/curated-worker-leads/contact-history.spec.d.ts +2 -0
  104. package/dist/curated-worker-leads/contact-history.spec.d.ts.map +1 -0
  105. package/dist/curated-worker-leads/contact-history.spec.js +88 -0
  106. package/dist/curated-worker-leads/contact-session.contract.spec.d.ts +2 -0
  107. package/dist/curated-worker-leads/contact-session.contract.spec.d.ts.map +1 -0
  108. package/dist/curated-worker-leads/contact-session.contract.spec.js +315 -0
  109. package/dist/curated-worker-leads/curated-worker-lead-config.contract.d.ts +489 -0
  110. package/dist/curated-worker-leads/curated-worker-lead-config.contract.d.ts.map +1 -0
  111. package/dist/curated-worker-leads/curated-worker-lead-config.contract.js +88 -0
  112. package/dist/curated-worker-leads/curated-worker-leads.contract.d.ts +135 -0
  113. package/dist/curated-worker-leads/curated-worker-leads.contract.d.ts.map +1 -0
  114. package/dist/curated-worker-leads/curated-worker-leads.contract.js +32 -0
  115. package/dist/curated-worker-leads/job-candidate-cards.spec.d.ts +2 -0
  116. package/dist/curated-worker-leads/job-candidate-cards.spec.d.ts.map +1 -0
  117. package/dist/curated-worker-leads/job-candidate-cards.spec.js +157 -0
  118. package/dist/curated-worker-leads/job-candidates.spec.d.ts +2 -0
  119. package/dist/curated-worker-leads/job-candidates.spec.d.ts.map +1 -0
  120. package/dist/curated-worker-leads/job-candidates.spec.js +140 -0
  121. package/dist/curated-worker-leads/job-feed-match-counts.contract.spec.d.ts +2 -0
  122. package/dist/curated-worker-leads/job-feed-match-counts.contract.spec.d.ts.map +1 -0
  123. package/dist/curated-worker-leads/job-feed-match-counts.contract.spec.js +19 -0
  124. package/dist/curated-worker-leads/jobs-tab.contract.d.ts +18547 -0
  125. package/dist/curated-worker-leads/jobs-tab.contract.d.ts.map +1 -0
  126. package/dist/curated-worker-leads/jobs-tab.contract.js +672 -0
  127. package/dist/curated-worker-leads/lead-agent-area.contract.d.ts +348 -0
  128. package/dist/curated-worker-leads/lead-agent-area.contract.d.ts.map +1 -0
  129. package/dist/curated-worker-leads/lead-agent-area.contract.js +51 -0
  130. package/dist/curated-worker-leads/owned-jobs-tab.contract.d.ts +1116 -0
  131. package/dist/curated-worker-leads/owned-jobs-tab.contract.d.ts.map +1 -0
  132. package/dist/curated-worker-leads/owned-jobs-tab.contract.js +93 -0
  133. package/dist/curated-workers/curated-filter-additions.spec.d.ts +2 -0
  134. package/dist/curated-workers/curated-filter-additions.spec.d.ts.map +1 -0
  135. package/dist/curated-workers/curated-filter-additions.spec.js +17 -0
  136. package/dist/curated-workers/curated-job-seeking.spec.d.ts +2 -0
  137. package/dist/curated-workers/curated-job-seeking.spec.d.ts.map +1 -0
  138. package/dist/curated-workers/curated-job-seeking.spec.js +53 -0
  139. package/dist/curated-workers/curated-workers-id-documents.spec.d.ts +2 -0
  140. package/dist/curated-workers/curated-workers-id-documents.spec.d.ts.map +1 -0
  141. package/dist/curated-workers/curated-workers-id-documents.spec.js +38 -0
  142. package/dist/curated-workers/curated-workers.contract.d.ts +6160 -1906
  143. package/dist/curated-workers/curated-workers.contract.d.ts.map +1 -1
  144. package/dist/curated-workers/curated-workers.contract.js +333 -51
  145. package/dist/dashboards/agent-daily-metrics.contract.d.ts +10 -10
  146. package/dist/dashboards/agent-daily-metrics.contract.js +1 -1
  147. package/dist/dashboards/dashboard-widgets.contract.d.ts +3777 -473
  148. package/dist/dashboards/dashboard-widgets.contract.d.ts.map +1 -1
  149. package/dist/dashboards/dashboard-widgets.contract.js +527 -29
  150. package/dist/dashboards/dashboard.contract.d.ts +8 -8
  151. package/dist/document-intake/document-intake.contract.d.ts +3132 -0
  152. package/dist/document-intake/document-intake.contract.d.ts.map +1 -0
  153. package/dist/document-intake/document-intake.contract.js +418 -0
  154. package/dist/export-jobs/export-jobs.contract.d.ts +3928 -0
  155. package/dist/export-jobs/export-jobs.contract.d.ts.map +1 -0
  156. package/dist/export-jobs/export-jobs.contract.js +240 -0
  157. package/dist/exports-events/exports-events.schemas.d.ts +90 -0
  158. package/dist/exports-events/exports-events.schemas.d.ts.map +1 -0
  159. package/dist/exports-events/exports-events.schemas.js +56 -0
  160. package/dist/files/files.contract.d.ts +133 -126
  161. package/dist/files/files.contract.d.ts.map +1 -1
  162. package/dist/files/files.contract.js +8 -0
  163. package/dist/health/health.contract.d.ts +4 -4
  164. package/dist/index.d.ts +86 -0
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +91 -1
  167. package/dist/interactions/interactions.contract.d.ts +162 -0
  168. package/dist/interactions/interactions.contract.d.ts.map +1 -0
  169. package/dist/interactions/interactions.contract.js +42 -0
  170. package/dist/job-clusters/job-clusters.contract.d.ts +1584 -0
  171. package/dist/job-clusters/job-clusters.contract.d.ts.map +1 -0
  172. package/dist/job-clusters/job-clusters.contract.js +133 -0
  173. package/dist/jobs/jobs.contract.d.ts +16662 -8628
  174. package/dist/jobs/jobs.contract.d.ts.map +1 -1
  175. package/dist/jobs/jobs.contract.js +403 -190
  176. package/dist/jobs/jobs.contract.spec.d.ts +2 -0
  177. package/dist/jobs/jobs.contract.spec.d.ts.map +1 -0
  178. package/dist/jobs/jobs.contract.spec.js +70 -0
  179. package/dist/kpi-impersonation/kpi-impersonation.contract.d.ts +75 -75
  180. package/dist/lead-assignments/lead-assignments.contract.d.ts +2933 -1122
  181. package/dist/lead-assignments/lead-assignments.contract.d.ts.map +1 -1
  182. package/dist/lead-assignments/lead-assignments.contract.js +29 -7
  183. package/dist/lead-distribution/agent-lead-distribution.contract.d.ts +328 -64
  184. package/dist/lead-distribution/agent-lead-distribution.contract.d.ts.map +1 -1
  185. package/dist/lead-distribution/agent-lead-distribution.contract.js +1 -1
  186. package/dist/lead-distribution/lead-distribution-config.contract.d.ts +31 -31
  187. package/dist/leads/leads.contract.d.ts +830 -368
  188. package/dist/leads/leads.contract.d.ts.map +1 -1
  189. package/dist/leads/leads.contract.js +106 -26
  190. package/dist/locations/locations.contract.d.ts +36 -36
  191. package/dist/notifications/notifications.contract.d.ts +1039 -0
  192. package/dist/notifications/notifications.contract.d.ts.map +1 -0
  193. package/dist/notifications/notifications.contract.js +110 -0
  194. package/dist/offices/offices.contract.d.ts +210 -60
  195. package/dist/offices/offices.contract.d.ts.map +1 -1
  196. package/dist/offices/offices.contract.js +18 -4
  197. package/dist/outreach/__tests__/outreach-claim.test.d.ts +2 -0
  198. package/dist/outreach/__tests__/outreach-claim.test.d.ts.map +1 -0
  199. package/dist/outreach/__tests__/outreach-claim.test.js +98 -0
  200. package/dist/outreach/__tests__/outreach-confirm-release.test.d.ts +2 -0
  201. package/dist/outreach/__tests__/outreach-confirm-release.test.d.ts.map +1 -0
  202. package/dist/outreach/__tests__/outreach-confirm-release.test.js +98 -0
  203. package/dist/outreach/__tests__/outreach-contract-additions.spec.d.ts +2 -0
  204. package/dist/outreach/__tests__/outreach-contract-additions.spec.d.ts.map +1 -0
  205. package/dist/outreach/__tests__/outreach-contract-additions.spec.js +78 -0
  206. package/dist/outreach/__tests__/outreach-requests.contract.spec.d.ts +2 -0
  207. package/dist/outreach/__tests__/outreach-requests.contract.spec.d.ts.map +1 -0
  208. package/dist/outreach/__tests__/outreach-requests.contract.spec.js +64 -0
  209. package/dist/outreach/__tests__/outreach-routes.test.d.ts +2 -0
  210. package/dist/outreach/__tests__/outreach-routes.test.d.ts.map +1 -0
  211. package/dist/outreach/__tests__/outreach-routes.test.js +57 -0
  212. package/dist/outreach/__tests__/outreach.schemas.test.d.ts +2 -0
  213. package/dist/outreach/__tests__/outreach.schemas.test.d.ts.map +1 -0
  214. package/dist/outreach/__tests__/outreach.schemas.test.js +144 -0
  215. package/dist/outreach/outreach-requests.contract.d.ts +1108 -0
  216. package/dist/outreach/outreach-requests.contract.d.ts.map +1 -0
  217. package/dist/outreach/outreach-requests.contract.js +134 -0
  218. package/dist/outreach/outreach-requests.schemas.d.ts +49 -0
  219. package/dist/outreach/outreach-requests.schemas.d.ts.map +1 -0
  220. package/dist/outreach/outreach-requests.schemas.js +60 -0
  221. package/dist/outreach/outreach.contract.d.ts +819 -0
  222. package/dist/outreach/outreach.contract.d.ts.map +1 -0
  223. package/dist/outreach/outreach.contract.js +195 -0
  224. package/dist/outreach/outreach.schemas.d.ts +118 -0
  225. package/dist/outreach/outreach.schemas.d.ts.map +1 -0
  226. package/dist/outreach/outreach.schemas.js +135 -0
  227. package/dist/own-research/own-research.contract.d.ts +1356 -552
  228. package/dist/own-research/own-research.contract.d.ts.map +1 -1
  229. package/dist/own-research/own-research.contract.js +14 -3
  230. package/dist/postcodes/postcodes.contract.d.ts +16 -16
  231. package/dist/proofs/proof-category.enum.d.ts +4 -0
  232. package/dist/proofs/proof-category.enum.d.ts.map +1 -0
  233. package/dist/proofs/proof-category.enum.js +5 -0
  234. package/dist/proofs/proof-entity-type.enum.d.ts +4 -0
  235. package/dist/proofs/proof-entity-type.enum.d.ts.map +1 -0
  236. package/dist/proofs/proof-entity-type.enum.js +5 -0
  237. package/dist/proofs/proof-type.enum.d.ts +28 -0
  238. package/dist/proofs/proof-type.enum.d.ts.map +1 -0
  239. package/dist/proofs/proof-type.enum.js +14 -0
  240. package/dist/proofs/proofs.contract.d.ts +3009 -0
  241. package/dist/proofs/proofs.contract.d.ts.map +1 -0
  242. package/dist/proofs/proofs.contract.js +92 -0
  243. package/dist/proofs/proofs.dtos.d.ts +1319 -0
  244. package/dist/proofs/proofs.dtos.d.ts.map +1 -0
  245. package/dist/proofs/proofs.dtos.js +178 -0
  246. package/dist/qualifications/qualifications.contract.d.ts +94 -94
  247. package/dist/realtime/data-changed.d.ts +21 -0
  248. package/dist/realtime/data-changed.d.ts.map +1 -0
  249. package/dist/realtime/data-changed.js +37 -0
  250. package/dist/shared/booking-history.schema.d.ts +27 -0
  251. package/dist/shared/booking-history.schema.d.ts.map +1 -0
  252. package/dist/shared/booking-history.schema.js +22 -0
  253. package/dist/shared/booking-history.spec.d.ts +2 -0
  254. package/dist/shared/booking-history.spec.d.ts.map +1 -0
  255. package/dist/shared/booking-history.spec.js +44 -0
  256. package/dist/shared/contact-suppressions.contract.d.ts +22 -0
  257. package/dist/shared/contact-suppressions.contract.d.ts.map +1 -0
  258. package/dist/shared/contact-suppressions.contract.js +13 -0
  259. package/dist/shared/live-booking.schema.d.ts +57 -0
  260. package/dist/shared/live-booking.schema.d.ts.map +1 -0
  261. package/dist/shared/live-booking.schema.js +34 -0
  262. package/dist/shared/summary-schemas.d.ts +218 -0
  263. package/dist/shared/summary-schemas.d.ts.map +1 -0
  264. package/dist/shared/summary-schemas.js +56 -0
  265. package/dist/sheets-sync/__tests__/sheets-sync-events.schemas.test.d.ts +2 -0
  266. package/dist/sheets-sync/__tests__/sheets-sync-events.schemas.test.d.ts.map +1 -0
  267. package/dist/sheets-sync/__tests__/sheets-sync-events.schemas.test.js +20 -0
  268. package/dist/sheets-sync/__tests__/tab-sync-config.schema.test.d.ts +2 -0
  269. package/dist/sheets-sync/__tests__/tab-sync-config.schema.test.d.ts.map +1 -0
  270. package/dist/sheets-sync/__tests__/tab-sync-config.schema.test.js +41 -0
  271. package/dist/sheets-sync/sheets-sync-events.schemas.d.ts +43 -0
  272. package/dist/sheets-sync/sheets-sync-events.schemas.d.ts.map +1 -0
  273. package/dist/sheets-sync/sheets-sync-events.schemas.js +29 -0
  274. package/dist/sheets-sync/sheets-sync.contract.d.ts +7258 -0
  275. package/dist/sheets-sync/sheets-sync.contract.d.ts.map +1 -0
  276. package/dist/sheets-sync/sheets-sync.contract.js +323 -0
  277. package/dist/telegram/telegram.contract.d.ts +727 -0
  278. package/dist/telegram/telegram.contract.d.ts.map +1 -0
  279. package/dist/telegram/telegram.contract.js +75 -0
  280. package/dist/trades/trade-rate-assessment.d.ts +18 -0
  281. package/dist/trades/trade-rate-assessment.d.ts.map +1 -0
  282. package/dist/trades/trade-rate-assessment.js +46 -0
  283. package/dist/trades/trade-rate-assessment.spec.d.ts +2 -0
  284. package/dist/trades/trade-rate-assessment.spec.d.ts.map +1 -0
  285. package/dist/trades/trade-rate-assessment.spec.js +223 -0
  286. package/dist/trades/trades.contract.d.ts +111 -0
  287. package/dist/trades/trades.contract.d.ts.map +1 -1
  288. package/dist/trades/trades.contract.js +49 -1
  289. package/dist/trades/trades.contract.spec.d.ts +2 -0
  290. package/dist/trades/trades.contract.spec.d.ts.map +1 -0
  291. package/dist/trades/trades.contract.spec.js +173 -0
  292. package/dist/user-access-grants/build-user-access-grant-rules.d.ts +10 -0
  293. package/dist/user-access-grants/build-user-access-grant-rules.d.ts.map +1 -0
  294. package/dist/user-access-grants/build-user-access-grant-rules.js +69 -0
  295. package/dist/user-access-grants/build-user-access-grant-rules.spec.d.ts +2 -0
  296. package/dist/user-access-grants/build-user-access-grant-rules.spec.d.ts.map +1 -0
  297. package/dist/user-access-grants/build-user-access-grant-rules.spec.js +77 -0
  298. package/dist/user-access-grants/user-access-grant-templates.json +454 -0
  299. package/dist/user-access-grants/user-access-grants.contract.d.ts +3886 -0
  300. package/dist/user-access-grants/user-access-grants.contract.d.ts.map +1 -0
  301. package/dist/user-access-grants/user-access-grants.contract.js +189 -0
  302. package/dist/user-access-grants/user-access-grants.contract.spec.d.ts +2 -0
  303. package/dist/user-access-grants/user-access-grants.contract.spec.d.ts.map +1 -0
  304. package/dist/user-access-grants/user-access-grants.contract.spec.js +149 -0
  305. package/dist/users/users.contract.d.ts +1959 -349
  306. package/dist/users/users.contract.d.ts.map +1 -1
  307. package/dist/users/users.contract.js +222 -37
  308. package/dist/users/users.contract.spec.d.ts +2 -0
  309. package/dist/users/users.contract.spec.d.ts.map +1 -0
  310. package/dist/users/users.contract.spec.js +103 -0
  311. package/dist/worker-identity-cases/worker-identity-cases.contract.d.ts +4609 -0
  312. package/dist/worker-identity-cases/worker-identity-cases.contract.d.ts.map +1 -0
  313. package/dist/worker-identity-cases/worker-identity-cases.contract.js +409 -0
  314. package/dist/worker-merge-proposals/worker-merge-proposals.contract.d.ts +1511 -0
  315. package/dist/worker-merge-proposals/worker-merge-proposals.contract.d.ts.map +1 -0
  316. package/dist/worker-merge-proposals/worker-merge-proposals.contract.js +150 -0
  317. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts +1106 -0
  318. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.d.ts.map +1 -0
  319. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.js +85 -0
  320. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.spec.d.ts +2 -0
  321. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.spec.d.ts.map +1 -0
  322. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.contract.spec.js +216 -0
  323. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.schemas.d.ts +453 -0
  324. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.schemas.d.ts.map +1 -0
  325. package/dist/worker-source-identity-conflicts/worker-source-identity-conflicts.schemas.js +109 -0
  326. package/dist/workers/do-not-contact.contract.d.ts +46 -0
  327. package/dist/workers/do-not-contact.contract.d.ts.map +1 -0
  328. package/dist/workers/do-not-contact.contract.js +41 -0
  329. package/dist/workers/do-not-contact.contract.spec.d.ts +2 -0
  330. package/dist/workers/do-not-contact.contract.spec.d.ts.map +1 -0
  331. package/dist/workers/do-not-contact.contract.spec.js +47 -0
  332. package/dist/workers/duplicate-group-worker.spec.d.ts +2 -0
  333. package/dist/workers/duplicate-group-worker.spec.d.ts.map +1 -0
  334. package/dist/workers/duplicate-group-worker.spec.js +34 -0
  335. package/dist/workers/filter-exact-flags.spec.d.ts +2 -0
  336. package/dist/workers/filter-exact-flags.spec.d.ts.map +1 -0
  337. package/dist/workers/filter-exact-flags.spec.js +37 -0
  338. package/dist/workers/worker-source-attribution.contract.spec.d.ts +2 -0
  339. package/dist/workers/worker-source-attribution.contract.spec.d.ts.map +1 -0
  340. package/dist/workers/worker-source-attribution.contract.spec.js +442 -0
  341. package/dist/workers/worker-source.spec.d.ts +2 -0
  342. package/dist/workers/worker-source.spec.d.ts.map +1 -0
  343. package/dist/workers/worker-source.spec.js +13 -0
  344. package/dist/workers/worker-status-facets.spec.d.ts +2 -0
  345. package/dist/workers/worker-status-facets.spec.d.ts.map +1 -0
  346. package/dist/workers/worker-status-facets.spec.js +34 -0
  347. package/dist/workers/workers.contract.d.ts +19534 -5969
  348. package/dist/workers/workers.contract.d.ts.map +1 -1
  349. package/dist/workers/workers.contract.js +1096 -113
  350. package/dist/workers/workers.contract.spec.d.ts +2 -0
  351. package/dist/workers/workers.contract.spec.d.ts.map +1 -0
  352. package/dist/workers/workers.contract.spec.js +31 -0
  353. package/package.json +5 -4
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.jobsContractRouter = exports.SearchJobResponseSchema = exports.SearchJobResultSchema = exports.SearchJobQuerySchema = exports.FilterMapMarkersSchema = exports.PaginatedJobResponseSchema = exports.FilterJobSchema = exports.BatchDeleteJobResponseSchema = exports.BatchDeleteJobSchema = exports.BatchUpdateJobResponseSchema = exports.BatchUpdateJobSchema = exports.UpdateJobSchema = exports.CreateDraftJobSchema = exports.CreateJobSchema = exports.JobMapMarkersResponseSchema = exports.JobMapMarkerSchema = exports.JobSchema = exports.CreateJobQualificationSchema = exports.JobQualificationSchema = exports.CreatePaySchema = exports.PaySchema = exports.JobSortableFieldsSchema = exports.JobStatusSchema = void 0;
3
+ exports.jobsContractRouter = exports.DuplicateJobConflictSchema = exports.SearchJobResponseSchema = exports.SearchJobResultSchema = exports.SearchJobQuerySchema = exports.FilterMapMarkersSchema = exports.PaginatedJobResponseSchema = exports.JobFeedResponseSchema = exports.JobFeedQuerySchema = exports.JOB_FEED_PAGE_SIZE = exports.FilterJobSchema = exports.BatchDeleteJobResponseSchema = exports.BatchDeleteJobSchema = exports.BatchUpdateJobResponseSchema = exports.BatchUpdateJobSchema = exports.UpdateJobSchema = exports.CreateJobSchema = exports.DemandBreakdownDetailResponseSchema = exports.DemandBreakdownDetailQuerySchema = exports.DemandUnitSchema = exports.DemandEpisodeSchema = exports.DemandBreakdownResponseSchema = exports.DemandBreakdownRowSchema = exports.DemandBreakdownFilterSchema = exports.DemandWindowSchema = exports.JobMapMarkersResponseSchema = exports.JobMapMarkerSchema = exports.PaginatedJobListResponseSchema = exports.FeedJobItemSchema = exports.JobListItemSchema = exports.JobSchema = exports.CreateJobQualificationSchema = exports.JobQualificationSchema = exports.CreatePaySchema = exports.PaySchema = exports.JobSortFieldMapping = exports.JobSortableFieldsSchema = exports.JobStartDateSchema = exports.CreationSourceSchema = exports.JobEventSchema = exports.JobCloseSourceSchema = exports.JobCloseReasonSchema = exports.JobEventTypeSchema = exports.JobStatusSchema = void 0;
4
4
  const zod_openapi_1 = require("@anatine/zod-openapi");
5
5
  const core_1 = require("@ts-rest/core");
6
6
  const zod_1 = require("zod");
@@ -9,13 +9,54 @@ const common_schemas_1 = require("../common/common-schemas");
9
9
  const error_schemas_1 = require("../common/error-schemas");
10
10
  const pagination_query_schema_1 = require("../common/pagination-query.schema");
11
11
  const pagination_schema_1 = require("../common/pagination.schema");
12
- const curated_workers_contract_1 = require("../curated-workers/curated-workers.contract");
12
+ const summary_schemas_1 = require("../shared/summary-schemas");
13
13
  const users_contract_1 = require("../users/users.contract");
14
14
  (0, zod_openapi_1.extendZodWithOpenApi)(zod_1.z);
15
15
  /**
16
16
  * Job Status Enum
17
17
  */
18
- exports.JobStatusSchema = zod_1.z.enum(['AVAILABLE', 'NOT_AVAILABLE', 'DRAFT']);
18
+ exports.JobStatusSchema = zod_1.z.enum(['AVAILABLE', 'NOT_AVAILABLE']);
19
+ /**
20
+ * Job lifecycle event log (job_events table) — read-only history.
21
+ * Mirrors apps/api JobEvent entity + its enums.
22
+ */
23
+ exports.JobEventTypeSchema = zod_1.z.enum([
24
+ 'CREATED',
25
+ 'STATUS_CHANGED',
26
+ 'POSITIONS_CHANGED',
27
+ ]);
28
+ exports.JobCloseReasonSchema = zod_1.z.enum([
29
+ 'FILLED',
30
+ 'PARTIALLY_FILLED',
31
+ 'UNFILLED',
32
+ ]);
33
+ exports.JobCloseSourceSchema = zod_1.z.enum([
34
+ 'BOOKINGS',
35
+ 'DECLARED',
36
+ 'EXPIRED',
37
+ 'START_DATE',
38
+ ]);
39
+ exports.JobEventSchema = zod_1.z.object({
40
+ id: zod_1.z.string().uuid(),
41
+ eventType: exports.JobEventTypeSchema,
42
+ fromStatus: exports.JobStatusSchema.nullable(),
43
+ toStatus: exports.JobStatusSchema.nullable(),
44
+ numberOfPositions: zod_1.z.number().int(),
45
+ previousNumberOfPositions: zod_1.z.number().int().nullable(),
46
+ filledPositions: zod_1.z.number().int().nullable(),
47
+ closeReason: exports.JobCloseReasonSchema.nullable(),
48
+ closeSource: exports.JobCloseSourceSchema.nullable(),
49
+ occurredAt: zod_1.z.union([zod_1.z.string().datetime(), zod_1.z.date()]),
50
+ });
51
+ /**
52
+ * Creation Source Enum
53
+ */
54
+ exports.CreationSourceSchema = zod_1.z.enum(['MANUAL', 'BOT']);
55
+ /** UK-local calendar date the job starts, e.g. '2026-07-14'. */
56
+ exports.JobStartDateSchema = zod_1.z
57
+ .string()
58
+ .regex(/^\d{4}-\d{2}-\d{2}$/, 'Expected YYYY-MM-DD')
59
+ .describe('Start date (UK-local calendar date)');
19
60
  /**
20
61
  * Job Sortable Fields Enum
21
62
  */
@@ -34,60 +75,71 @@ exports.JobSortableFieldsSchema = zod_1.z
34
75
  'receivedRate',
35
76
  'workHours',
36
77
  'qualificationsCount',
78
+ 'creationSource',
37
79
  'createdAt',
38
80
  'updatedAt',
81
+ 'startDate',
39
82
  ])
40
83
  .openapi({ title: 'JobSortableFields' });
84
+ /** Maps sort field values to ability field paths on SortJobSchema. */
85
+ exports.JobSortFieldMapping = {
86
+ description: 'description',
87
+ numberOfPositions: 'numberOfPositions',
88
+ status: 'status',
89
+ tradeId: 'tradeId',
90
+ collaborationCompany: 'collaboration.companyId',
91
+ collaborationClient: 'collaboration.clientId',
92
+ collaborationAgent: 'collaboration.userId',
93
+ distance: 'distance',
94
+ postcode: 'postcode',
95
+ payRate: 'payRate',
96
+ receivedRate: 'receivedRate',
97
+ workHours: 'workHours',
98
+ qualificationsCount: 'qualificationsCount',
99
+ creationSource: 'creationSource',
100
+ createdAt: 'createdAt',
101
+ updatedAt: 'updatedAt',
102
+ startDate: 'startDate',
103
+ };
41
104
  /**
42
105
  * Pay Schema - Nested object for job payment details
43
106
  */
44
107
  exports.PaySchema = zod_1.z
45
108
  .object({
46
- rateUnit: common_schemas_1.RateUnitSchema.describe('The unit for the pay rate'),
47
- isNegotiable: zod_1.z
48
- .boolean()
49
- .default(false)
50
- .describe('Whether the rate is negotiable'),
51
- rate: zod_1.z.coerce
52
- .number()
53
- .min(1)
54
- .nullable()
55
- .optional()
56
- .describe('The pay rate'),
109
+ rateUnit: common_schemas_1.RateUnitSchema.describe('Hourly or Daily'),
110
+ isNegotiable: zod_1.z.boolean().default(false).describe('Negotiable'),
111
+ rate: zod_1.z.coerce.number().min(1).nullable().optional().describe('e.g. 15.00'),
57
112
  rateMax: zod_1.z.coerce
58
113
  .number()
59
114
  .min(1)
60
115
  .nullable()
61
116
  .optional()
62
- .describe('The maximum pay rate (for a range)'),
117
+ .describe('e.g. 20.00'),
63
118
  receivedRate: zod_1.z.coerce
64
119
  .number()
65
120
  .min(1)
66
121
  .nullable()
67
122
  .optional()
68
- .describe('The received pay rate'),
123
+ .describe('e.g. 18.00'),
69
124
  })
70
125
  .openapi({ title: 'Pay' });
71
126
  exports.CreatePaySchema = zod_1.z
72
127
  .object({
73
- rateUnit: common_schemas_1.RateUnitSchema.default('HOURLY').describe('The unit for the pay rate'),
74
- isNegotiable: zod_1.z
75
- .boolean()
76
- .default(false)
77
- .describe('Whether the rate is negotiable'),
78
- rate: zod_1.z.number().min(1).nullable().optional().describe('The pay rate'),
128
+ rateUnit: common_schemas_1.RateUnitSchema.default('HOURLY').describe('Pay rate'),
129
+ isNegotiable: zod_1.z.boolean().default(false).describe('Negotiable'),
130
+ rate: zod_1.z.number().min(1).nullable().optional().describe('Pay rate'),
79
131
  rateMax: zod_1.z
80
132
  .number()
81
133
  .min(1)
82
134
  .optional()
83
135
  .nullable()
84
- .describe('The maximum pay rate (for a range)'),
136
+ .describe('Maximum pay rate'),
85
137
  receivedRate: zod_1.z
86
138
  .number()
87
139
  .min(1)
88
140
  .nullable()
89
141
  .optional()
90
- .describe('The received pay rate'),
142
+ .describe('Received rate'),
91
143
  })
92
144
  .superRefine((data, ctx) => {
93
145
  if (!data.isNegotiable) {
@@ -121,13 +173,13 @@ exports.CreatePaySchema = zod_1.z
121
173
  exports.JobQualificationSchema = zod_1.z
122
174
  .object({
123
175
  id: zod_1.z.string().uuid().describe('The ID of the job qualification'),
124
- qualificationId: zod_1.z.string().uuid().describe('The ID of the qualification'),
176
+ qualificationId: zod_1.z.string().uuid().describe('Qualification'),
125
177
  qualificationTypeId: zod_1.z
126
178
  .string()
127
179
  .uuid()
128
180
  .optional()
129
181
  .nullable()
130
- .describe('The ID of the qualification type'),
182
+ .describe('Qualification type'),
131
183
  })
132
184
  .openapi({ title: 'JobQualification' });
133
185
  exports.CreateJobQualificationSchema = zod_1.z
@@ -136,7 +188,7 @@ exports.CreateJobQualificationSchema = zod_1.z
136
188
  qualificationTypeId: zod_1.z
137
189
  .union([zod_1.z.string().uuid(), zod_1.z.null()])
138
190
  .optional()
139
- .describe('The ID of the qualification type'),
191
+ .describe('Qualification type'),
140
192
  })
141
193
  .openapi({ title: 'CreateJobQualification' });
142
194
  /**
@@ -145,24 +197,18 @@ exports.CreateJobQualificationSchema = zod_1.z
145
197
  exports.JobSchema = zod_1.z
146
198
  .object({
147
199
  id: zod_1.z.string().uuid().describe('Job ID'),
148
- description: zod_1.z.string().describe('Job Description'),
149
- numberOfPositions: zod_1.z
150
- .number()
151
- .int()
152
- .min(1)
153
- .describe('Number of Positions Available'),
200
+ description: zod_1.z.string().describe('Description'),
201
+ numberOfPositions: zod_1.z.number().int().min(1).describe('Positions'),
154
202
  workHours: zod_1.z.coerce
155
203
  .number()
156
204
  .min(0.01)
157
205
  .max(60)
158
206
  .optional()
159
207
  .nullable()
160
- .describe('Number of Work Hours'),
161
- status: exports.JobStatusSchema.describe('Job Status'),
208
+ .describe('Work Hours'),
209
+ status: exports.JobStatusSchema.describe('Status'),
162
210
  pay: exports.PaySchema.describe('Payment Details'),
163
- location: common_schemas_1.LocationDetailsSchema.optional()
164
- .nullable()
165
- .describe('Job Location'),
211
+ location: common_schemas_1.LocationDetailsSchema.optional().nullable().describe('Location'),
166
212
  tradeId: zod_1.z
167
213
  .string()
168
214
  .min(1, { message: 'Trade is required' })
@@ -172,10 +218,10 @@ exports.JobSchema = zod_1.z
172
218
  .array(exports.JobQualificationSchema)
173
219
  .optional()
174
220
  .default([])
175
- .describe('Job Qualifications'),
176
- currentCollaboration: collaborations_contract_1.CollaborationSchema.nullable()
221
+ .describe('Qualifications'),
222
+ collaboration: collaborations_contract_1.CollaborationSchema.nullable()
177
223
  .optional()
178
- .describe('Current Collaboration'),
224
+ .describe('Collaboration'),
179
225
  createdAt: zod_1.z
180
226
  .union([zod_1.z.string().datetime(), zod_1.z.date()])
181
227
  .transform((val) => (val instanceof Date ? val.toISOString() : val))
@@ -193,6 +239,9 @@ exports.JobSchema = zod_1.z
193
239
  createdBy: users_contract_1.UserSchema.nullable()
194
240
  .optional()
195
241
  .describe('User who created the job'),
242
+ creationSource: exports.CreationSourceSchema.nullable()
243
+ .optional()
244
+ .describe('How the job was created (BOT or MANUAL)'),
196
245
  distanceKm: zod_1.z.number().nullable().optional().describe('Distance in KM'),
197
246
  filledPositions: zod_1.z
198
247
  .number()
@@ -200,8 +249,58 @@ exports.JobSchema = zod_1.z
200
249
  .min(0)
201
250
  .default(0)
202
251
  .describe('Number of filled positions in the current availability window (computed from qualifying bookings)'),
252
+ startDate: exports.JobStartDateSchema.nullable().describe('Start date'),
203
253
  })
204
254
  .openapi({ title: 'Job' });
255
+ /**
256
+ * JobListItemSchema - Lightweight schema for job list views.
257
+ * Uses summary nested types instead of full entity schemas to reduce payload size.
258
+ * Key differences from JobSchema:
259
+ * - `location` uses LocationSummarySchema (4 fields) instead of LocationDetailsSchema (9 fields)
260
+ * - `collaboration` uses CollaborationSummarySchema instead of full CollaborationSchema
261
+ * - `createdBy` uses UserSummarySchema (shown as FA on jobs with no collaboration)
262
+ */
263
+ exports.JobListItemSchema = zod_1.z
264
+ .object({
265
+ id: zod_1.z.string().uuid(),
266
+ description: zod_1.z.string(),
267
+ numberOfPositions: zod_1.z.coerce.number().int().min(1),
268
+ workHours: zod_1.z.coerce.number().nullable().optional(),
269
+ status: exports.JobStatusSchema,
270
+ pay: exports.PaySchema,
271
+ location: summary_schemas_1.LocationSummarySchema.nullable().optional(),
272
+ tradeId: zod_1.z.string().uuid(),
273
+ jobQualifications: zod_1.z.array(exports.JobQualificationSchema).nullable().optional(),
274
+ collaboration: summary_schemas_1.CollaborationSummarySchema.nullable().optional(),
275
+ createdAt: zod_1.z
276
+ .union([zod_1.z.string().datetime(), zod_1.z.date()])
277
+ .transform((val) => (val instanceof Date ? val.toISOString() : val)),
278
+ updatedAt: zod_1.z
279
+ .union([zod_1.z.string().datetime(), zod_1.z.date()])
280
+ .transform((val) => (val instanceof Date ? val.toISOString() : val)),
281
+ createdById: zod_1.z.string().uuid().nullable().optional(),
282
+ createdBy: summary_schemas_1.UserSummarySchema.nullable().optional(),
283
+ creationSource: exports.CreationSourceSchema.nullable().optional(),
284
+ distanceKm: zod_1.z.coerce.number().nullable().optional(),
285
+ filledPositions: zod_1.z.coerce.number().int().min(0).default(0),
286
+ startDate: exports.JobStartDateSchema.nullable().optional().describe('Start date'),
287
+ })
288
+ .openapi({ title: 'JobListItem' });
289
+ // FeedJobItem mirrors JobListItem (flat tradeId, JobQualificationSchema-shaped
290
+ // jobQualifications) — names for trades/qualifications are resolved on the
291
+ // client from the shared trades/qualifications context, not denormalized here.
292
+ exports.FeedJobItemSchema = exports.JobListItemSchema.extend({
293
+ // Legacy/imported jobs may not have a trade. The jobs table deliberately
294
+ // permits this and the feed UI renders an explicit no-trade state.
295
+ tradeId: zod_1.z.string().uuid().nullable(),
296
+ availableSince: zod_1.z
297
+ .union([zod_1.z.string().datetime(), zod_1.z.date()])
298
+ .transform((val) => (val instanceof Date ? val.toISOString() : val))
299
+ .nullable(),
300
+ }).openapi({ title: 'FeedJobItem' });
301
+ exports.PaginatedJobListResponseSchema = (0, pagination_schema_1.createPaginatedResponseSchema)(exports.JobListItemSchema)
302
+ .describe('Jobs retrieved successfully')
303
+ .openapi({ title: 'JobListPaginatedResponse' });
205
304
  /**
206
305
  * Lightweight schema for map marker data.
207
306
  * Contains only the fields needed to place and identify markers on a map.
@@ -215,13 +314,23 @@ exports.JobMapMarkerSchema = zod_1.z
215
314
  latitude: zod_1.z.number().describe('Latitude coordinate'),
216
315
  longitude: zod_1.z.number().describe('Longitude coordinate'),
217
316
  postcode: zod_1.z.string().nullable().optional().describe('Postcode'),
218
- numberOfPositions: zod_1.z.number().int().min(1).describe('Number of positions'),
317
+ numberOfPositions: zod_1.z.number().int().min(1).describe('Positions'),
219
318
  filledPositions: zod_1.z
220
319
  .number()
221
320
  .int()
222
321
  .min(0)
223
322
  .default(0)
224
323
  .describe('Filled positions count'),
324
+ createdAt: zod_1.z
325
+ .string()
326
+ .datetime()
327
+ .describe('Job creation timestamp (ISO) — used for demand-trend bucketing'),
328
+ clusterId: zod_1.z
329
+ .string()
330
+ .uuid()
331
+ .nullable()
332
+ .optional()
333
+ .describe("Id of this job's CONFIRMED duplicate cluster, or null. The Breakdown collapses markers sharing a clusterId into one demand unit."),
225
334
  })
226
335
  .openapi({ title: 'JobMapMarker' });
227
336
  exports.JobMapMarkersResponseSchema = zod_1.z
@@ -231,37 +340,129 @@ exports.JobMapMarkersResponseSchema = zod_1.z
231
340
  excludedCount: zod_1.z
232
341
  .number()
233
342
  .int()
234
- .describe('Jobs excluded due to missing coordinates'),
343
+ .describe('Jobs beyond the 1000-marker render cap (all returned markers have coordinates)'),
235
344
  })
236
345
  .openapi({ title: 'JobMapMarkersResponse' });
237
346
  /**
238
- * Create Job Schema
347
+ * Demand/Supply breakdown (spec 2026-07-11-demand-supply-accuracy-design).
348
+ * A "demand unit" is a cluster-deduped availability episode island; see
349
+ * apps/api demand-breakdown.sql.ts for derivation.
239
350
  */
240
- exports.CreateJobSchema = zod_1.z
351
+ exports.DemandWindowSchema = zod_1.z
241
352
  .object({
242
- description: zod_1.z.string().min(10).describe('Job Description'),
243
- location: common_schemas_1.CreateLocationSchema.optional()
244
- .nullable()
245
- .describe('Job Location'),
246
- numberOfPositions: zod_1.z
353
+ from: zod_1.z.string().date().describe('Window start (inclusive, yyyy-MM-dd)'),
354
+ to: zod_1.z.string().date().describe('Window end (inclusive, yyyy-MM-dd)'),
355
+ })
356
+ .refine((w) => w.from <= w.to, { message: 'window.from must be <= window.to' })
357
+ .refine((w) => (Date.parse(w.to) - Date.parse(w.from)) / 86400000 <= 366, { message: 'window must span at most 366 days' })
358
+ .openapi({ title: 'DemandWindow' });
359
+ const demandBreakdownFilterShape = {
360
+ window: exports.DemandWindowSchema,
361
+ tradeId: zod_1.z.string().uuid().optional().nullable().describe('Filter by trade'),
362
+ companyId: zod_1.z.string().uuid().optional().nullable().describe('Search Company'),
363
+ clientId: zod_1.z.string().uuid().optional().nullable().describe('Search Client'),
364
+ userId: zod_1.z.string().uuid().optional().nullable().describe('Search First Agent'),
365
+ location: common_schemas_1.LocationFilterSchema.optional().nullable().describe('Filter by location'),
366
+ pay: common_schemas_1.PayRangeSchema.optional().nullable().describe('Filter by pay rate range'),
367
+ qualificationFilters: zod_1.z
368
+ .array(common_schemas_1.QualificationFilterSchema)
369
+ .optional()
370
+ .describe('Qualifications'),
371
+ };
372
+ exports.DemandBreakdownFilterSchema = zod_1.z
373
+ .object(demandBreakdownFilterShape)
374
+ .openapi({ title: 'DemandBreakdownFilter' });
375
+ exports.DemandBreakdownRowSchema = zod_1.z
376
+ .object({
377
+ area: zod_1.z.string().describe('Postcode area (outward letters, e.g. "SW")'),
378
+ tradeId: zod_1.z.string().uuid(),
379
+ tradeName: zod_1.z.string(),
380
+ units: zod_1.z.number().int().describe('Demand units in window (cluster-deduped)'),
381
+ episodes: zod_1.z.number().int().describe('Raw episodes folded into those units'),
382
+ positionEpisodes: zod_1.z
247
383
  .number()
248
384
  .int()
249
- .min(1)
250
- .max(100)
251
- .describe('Number of Positions'),
252
- workHours: zod_1.z
385
+ .describe('Σ unit positions (post-collapse) — the flow numerator'),
386
+ filledInWindow: zod_1.z
253
387
  .number()
254
- .min(0.01)
255
- .max(60)
256
- .default(8)
257
- .describe('Number of Work Hours'),
258
- pay: exports.CreatePaySchema.describe('Payment Details'),
388
+ .int()
389
+ .describe('Filled-status bookings created in window on scoped jobs'),
390
+ stockUnfilled: zod_1.z
391
+ .number()
392
+ .int()
393
+ .describe('Unfilled positions on currently-AVAILABLE jobs (deduped)'),
394
+ unitsFirstHalf: zod_1.z.number().int(),
395
+ unitsSecondHalf: zod_1.z.number().int(),
396
+ centroidLongitude: zod_1.z.number().nullable(),
397
+ centroidLatitude: zod_1.z.number().nullable(),
398
+ })
399
+ .openapi({ title: 'DemandBreakdownRow' });
400
+ exports.DemandBreakdownResponseSchema = zod_1.z
401
+ .object({
402
+ rows: zod_1.z.array(exports.DemandBreakdownRowSchema),
403
+ totals: zod_1.z.object({
404
+ units: zod_1.z.number().int(),
405
+ episodes: zod_1.z.number().int(),
406
+ positionEpisodes: zod_1.z.number().int(),
407
+ filledInWindow: zod_1.z.number().int(),
408
+ stockUnfilled: zod_1.z.number().int(),
409
+ }),
410
+ excludedNoLocation: zod_1.z
411
+ .number()
412
+ .int()
413
+ .describe('Scoped jobs skipped: missing/unparseable postcode'),
414
+ excludedNoTrade: zod_1.z.number().int().describe('Scoped jobs skipped: no trade'),
415
+ })
416
+ .openapi({ title: 'DemandBreakdownResponse' });
417
+ exports.DemandEpisodeSchema = zod_1.z
418
+ .object({
419
+ jobId: zod_1.z.string().uuid(),
420
+ occurredAt: zod_1.z.string().describe('Episode timestamp (ISO)'),
421
+ positions: zod_1.z.number().int(),
422
+ kind: zod_1.z.enum(['CREATED', 'REOPEN']),
423
+ })
424
+ .openapi({ title: 'DemandEpisode' });
425
+ exports.DemandUnitSchema = zod_1.z
426
+ .object({
427
+ unitStart: zod_1.z.string().describe('First episode timestamp (ISO)'),
428
+ positions: zod_1.z.number().int().describe('Max positions across merged episodes'),
429
+ clusterStatus: zod_1.z.enum(['CONFIRMED', 'PENDING', 'NONE']),
430
+ episodes: zod_1.z.array(exports.DemandEpisodeSchema),
431
+ jobs: zod_1.z.array(zod_1.z.object({
432
+ jobId: zod_1.z.string().uuid(),
433
+ status: exports.JobStatusSchema,
434
+ positions: zod_1.z.number().int(),
435
+ })),
436
+ filledInWindow: zod_1.z.number().int(),
437
+ stockUnfilled: zod_1.z.number().int(),
438
+ })
439
+ .openapi({ title: 'DemandUnit' });
440
+ exports.DemandBreakdownDetailQuerySchema = zod_1.z
441
+ .object({
442
+ ...demandBreakdownFilterShape,
443
+ area: zod_1.z.string().min(1).describe('Postcode area key, e.g. "SW"'),
444
+ tradeId: zod_1.z.string().uuid().describe('Trade (required here)'),
445
+ })
446
+ .openapi({ title: 'DemandBreakdownDetailQuery' });
447
+ exports.DemandBreakdownDetailResponseSchema = zod_1.z
448
+ .object({ units: zod_1.z.array(exports.DemandUnitSchema) })
449
+ .openapi({ title: 'DemandBreakdownDetailResponse' });
450
+ /**
451
+ * Create Job Schema
452
+ */
453
+ exports.CreateJobSchema = zod_1.z
454
+ .object({
455
+ description: zod_1.z.string().min(10).describe('Description'),
456
+ location: common_schemas_1.CreateLocationSchema.optional().nullable().describe('Location'),
259
457
  tradeId: zod_1.z
260
458
  .string()
261
459
  .min(1, { message: 'Trade is required' })
262
460
  .pipe(zod_1.z.string().uuid())
263
461
  .describe('Trade'),
264
- currentCollaboration: zod_1.z
462
+ numberOfPositions: zod_1.z.number().int().min(1).max(100).describe('Positions'),
463
+ workHours: zod_1.z.number().min(0.01).max(60).default(8).describe('Work Hours'),
464
+ pay: exports.CreatePaySchema.describe('Payment Details'),
465
+ collaboration: zod_1.z
265
466
  .object({
266
467
  id: zod_1.z
267
468
  .string()
@@ -271,85 +472,51 @@ exports.CreateJobSchema = zod_1.z
271
472
  })
272
473
  .optional()
273
474
  .nullable()
274
- .describe('Current Collaboration'),
475
+ .describe('Collaboration'),
476
+ status: exports.JobStatusSchema.optional().describe('Status'),
275
477
  jobQualifications: zod_1.z
276
478
  .array(exports.CreateJobQualificationSchema)
277
479
  .optional()
278
- .describe('Job Qualifications'),
279
- status: exports.JobStatusSchema.optional().describe('Job Status'),
280
- })
281
- .superRefine((data, ctx) => {
282
- // If no collaboration is provided, status must be DRAFT (or will default to DRAFT)
283
- const hasCollaboration = data.currentCollaboration && data.currentCollaboration.id;
284
- if (!hasCollaboration) {
285
- // If status is explicitly set to non-DRAFT, fail validation
286
- if (data.status !== undefined && data.status !== 'DRAFT') {
287
- ctx.addIssue({
288
- code: zod_1.z.ZodIssueCode.custom,
289
- message: 'A collaboration is required when creating a job with non-draft status.',
290
- path: ['currentCollaboration'],
291
- });
292
- }
293
- }
294
- })
295
- .transform((data) => {
296
- // If no collaboration, default status to DRAFT
297
- const hasCollaboration = data.currentCollaboration && data.currentCollaboration.id;
298
- return {
299
- ...data,
300
- status: hasCollaboration ? (data.status ?? 'AVAILABLE') : 'DRAFT',
301
- };
480
+ .describe('Qualifications'),
481
+ acknowledgedDuplicateIds: zod_1.z
482
+ .array(zod_1.z.string().uuid())
483
+ .optional()
484
+ .describe('Ids of suspected-duplicate jobs the creator has reviewed and confirmed are NOT the same job. Presence (even empty) skips the duplicate probe and records rejected pairs against these ids.'),
485
+ startDate: exports.JobStartDateSchema.nullable().optional(),
302
486
  })
487
+ .transform((data) => ({
488
+ ...data,
489
+ status: data.status ?? 'AVAILABLE',
490
+ }))
303
491
  .openapi({ title: 'CreateJob' });
304
492
  /**
305
- * Create Draft Job Schema - For bot-created jobs without collaboration
493
+ * Update Job Schema
306
494
  */
307
- exports.CreateDraftJobSchema = zod_1.z
495
+ exports.UpdateJobSchema = zod_1.z
308
496
  .object({
309
- description: zod_1.z.string().min(10).describe('Job Description'),
310
- location: common_schemas_1.CreateLocationSchema.optional()
311
- .nullable()
312
- .describe('Job Location'),
313
- numberOfPositions: zod_1.z
314
- .number()
315
- .int()
316
- .min(1)
317
- .max(100)
318
- .describe('Number of Positions'),
319
- workHours: zod_1.z
320
- .number()
321
- .min(0.01)
322
- .max(60)
323
- .default(8)
324
- .describe('Number of Work Hours'),
325
- pay: exports.CreatePaySchema.describe('Payment Details'),
497
+ description: zod_1.z.string().min(10).optional().describe('Description'),
498
+ location: common_schemas_1.CreateLocationSchema.optional().nullable().describe('Location'),
326
499
  tradeId: zod_1.z
327
500
  .string()
328
501
  .min(1, { message: 'Trade is required' })
329
502
  .pipe(zod_1.z.string().uuid())
330
- .describe('Trade'),
331
- jobQualifications: zod_1.z
332
- .array(exports.CreateJobQualificationSchema)
333
503
  .optional()
334
- .describe('Job Qualifications'),
335
- })
336
- .openapi({ title: 'CreateDraftJob' });
337
- /**
338
- * Update Job Schema
339
- */
340
- exports.UpdateJobSchema = zod_1.z
341
- .object({
342
- description: zod_1.z.string().min(10).optional().describe('Job Description'),
343
- location: common_schemas_1.CreateLocationSchema.optional()
344
- .nullable()
345
- .describe('Job Location'),
504
+ .describe('Trade'),
346
505
  numberOfPositions: zod_1.z
347
506
  .number()
348
507
  .int()
349
508
  .min(1)
350
509
  .max(100)
351
510
  .optional()
352
- .describe('Number of Positions'),
511
+ .describe('Positions'),
512
+ positionsAreRemaining: zod_1.z
513
+ .boolean()
514
+ .optional()
515
+ .describe('When true, numberOfPositions is the count STILL NEEDED (remaining); the API sets total = currentFilled + numberOfPositions. Omitted/false = absolute total. Set by the bot on reposts; never by the web form.'),
516
+ declaredFilled: zod_1.z
517
+ .boolean()
518
+ .optional()
519
+ .describe('When closing a job (status -> NOT_AVAILABLE), marks it as DECLARED filled (sourced externally, e.g. a "filled" reply in the group) rather than the default BOOKINGS-derived close. Set by the bot on "filled" closes only; never by the web form or on cancellations.'),
353
520
  workHours: zod_1.z
354
521
  .number()
355
522
  .min(0.01)
@@ -357,13 +524,7 @@ exports.UpdateJobSchema = zod_1.z
357
524
  .optional()
358
525
  .describe('Number of Work Hours'),
359
526
  pay: exports.CreatePaySchema.optional().describe('Payment Details'),
360
- tradeId: zod_1.z
361
- .string()
362
- .min(1, { message: 'Trade is required' })
363
- .pipe(zod_1.z.string().uuid())
364
- .optional()
365
- .describe('Trade'),
366
- currentCollaboration: zod_1.z
527
+ collaboration: zod_1.z
367
528
  .preprocess((val) => (val === '' ? null : val), zod_1.z
368
529
  .object({
369
530
  id: zod_1.z
@@ -385,32 +546,13 @@ exports.UpdateJobSchema = zod_1.z
385
546
  }
386
547
  return val;
387
548
  })
388
- .describe('Current Collaboration'),
549
+ .describe('Collaboration'),
550
+ status: exports.JobStatusSchema.optional().describe('Job Status'),
389
551
  jobQualifications: zod_1.z
390
552
  .array(exports.CreateJobQualificationSchema)
391
553
  .optional()
392
554
  .describe('Job Qualifications'),
393
- status: exports.JobStatusSchema.optional().describe('Job Status'),
394
- })
395
- .superRefine((data, ctx) => {
396
- // If status is being set to something other than DRAFT,
397
- // and currentCollaboration is null or an empty object (form with no selection),
398
- // then require a collaboration.
399
- // Note: We check for null or missing id specifically, not `!data.currentCollaboration`,
400
- // because undefined means the field wasn't provided in the request (PATCH),
401
- // and the service layer will handle checking the existing job's collaboration.
402
- const hasNoCollaboration = data.currentCollaboration === null ||
403
- (data.currentCollaboration !== undefined &&
404
- !data.currentCollaboration.id);
405
- if (data.status !== undefined &&
406
- data.status !== 'DRAFT' &&
407
- hasNoCollaboration) {
408
- ctx.addIssue({
409
- code: zod_1.z.ZodIssueCode.custom,
410
- message: 'A collaboration is required when setting status to a non-draft value.',
411
- path: ['currentCollaboration'],
412
- });
413
- }
555
+ startDate: exports.JobStartDateSchema.nullable().optional(),
414
556
  })
415
557
  .openapi({ title: 'UpdateJob' });
416
558
  exports.BatchUpdateJobSchema = zod_1.z
@@ -446,40 +588,62 @@ exports.BatchDeleteJobResponseSchema = zod_1.z
446
588
  * Filter Job Schema
447
589
  */
448
590
  exports.FilterJobSchema = pagination_query_schema_1.PaginationQuerySchema.extend({
449
- tradeId: zod_1.z.string().uuid().optional().nullable().describe('Filter by trade'),
450
- qualificationFilters: zod_1.z
451
- .array(curated_workers_contract_1.QualificationFilterSchema)
452
- .optional()
453
- .describe('Filter by qualifications'),
454
- status: exports.JobStatusSchema.optional()
591
+ status: exports.JobStatusSchema.optional().nullable().describe('Status'),
592
+ creationSource: exports.CreationSourceSchema.optional()
455
593
  .nullable()
456
- .describe('Filter by job status'),
594
+ .describe('Filter by creation source'),
595
+ tradeId: zod_1.z.string().uuid().optional().nullable().describe('Filter by trade'),
596
+ description: zod_1.z.string().optional().nullable().describe('Paste job post'),
597
+ companyId: zod_1.z.string().uuid().optional().nullable().describe('Search Company'),
598
+ clientId: zod_1.z.string().uuid().optional().nullable().describe('Search Client'),
457
599
  userId: zod_1.z
458
600
  .string()
459
601
  .uuid()
460
602
  .optional()
461
603
  .nullable()
462
604
  .describe('Search First Agent'),
463
- clientId: zod_1.z.string().uuid().optional().nullable().describe('Search Client'),
464
- companyId: zod_1.z.string().uuid().optional().nullable().describe('Search Company'),
465
605
  location: common_schemas_1.LocationFilterSchema.optional()
466
606
  .nullable()
467
607
  .describe('Filter by location'),
468
608
  pay: common_schemas_1.PayRangeSchema.optional()
469
609
  .nullable()
470
610
  .describe('Filter by pay rate range'),
471
- sortBy: exports.JobSortableFieldsSchema.optional()
472
- .nullable()
473
- .describe('The field to sort the results by'),
474
- sortOrder: common_schemas_1.SortOrderSchema.optional()
475
- .nullable()
476
- .describe('The order to sort the results by'),
611
+ qualificationFilters: zod_1.z
612
+ .array(common_schemas_1.QualificationFilterSchema)
613
+ .optional()
614
+ .describe('Qualifications'),
477
615
  createdAt: common_schemas_1.DateRangeSchema.optional()
478
616
  .nullable()
479
617
  .describe('Filter by created date range'),
480
618
  updatedAt: common_schemas_1.DateRangeSchema.optional()
481
619
  .nullable()
482
620
  .describe('Filter by updated date range'),
621
+ // Not a jobs column — the API resolves this to an EXISTS against
622
+ // outreach_requests. Defined inline rather than reusing workers.contract's
623
+ // BooleanFilterSchema: that would add a jobs -> workers contract import for a
624
+ // two-value enum, and its `unknown` member has no meaning here.
625
+ outreachRequested: zod_1.z
626
+ .enum(['only_with', 'only_without'])
627
+ .optional()
628
+ .nullable()
629
+ .describe('Marked for outreach'),
630
+ sort: (0, common_schemas_1.createSortArraySchema)(exports.JobSortableFieldsSchema),
631
+ });
632
+ exports.JOB_FEED_PAGE_SIZE = 300;
633
+ exports.JobFeedQuerySchema = exports.FilterJobSchema.extend({
634
+ page: zod_1.z.coerce.number().int().min(1).default(1),
635
+ limit: zod_1.z.coerce
636
+ .number()
637
+ .int()
638
+ .min(1)
639
+ .max(exports.JOB_FEED_PAGE_SIZE)
640
+ .default(exports.JOB_FEED_PAGE_SIZE),
641
+ });
642
+ exports.JobFeedResponseSchema = zod_1.z.object({
643
+ items: exports.FeedJobItemSchema.array().max(exports.JOB_FEED_PAGE_SIZE),
644
+ page: zod_1.z.number().int().min(1),
645
+ limit: zod_1.z.number().int().min(1).max(exports.JOB_FEED_PAGE_SIZE),
646
+ hasMore: zod_1.z.boolean(),
483
647
  });
484
648
  exports.PaginatedJobResponseSchema = (0, pagination_schema_1.createPaginatedResponseSchema)(exports.JobSchema)
485
649
  .describe('Jobs retrieved successfully')
@@ -488,34 +652,32 @@ exports.PaginatedJobResponseSchema = (0, pagination_schema_1.createPaginatedResp
488
652
  * Filter schema for map markers — same filters as job list, but no pagination.
489
653
  */
490
654
  exports.FilterMapMarkersSchema = zod_1.z.object({
655
+ status: exports.JobStatusSchema.optional().nullable().describe('Status'),
491
656
  tradeId: zod_1.z.string().uuid().optional().nullable().describe('Filter by trade'),
492
- status: exports.JobStatusSchema.optional()
493
- .nullable()
494
- .describe('Filter by job status'),
657
+ companyId: zod_1.z.string().uuid().optional().nullable().describe('Search Company'),
658
+ clientId: zod_1.z.string().uuid().optional().nullable().describe('Search Client'),
495
659
  userId: zod_1.z
496
660
  .string()
497
661
  .uuid()
498
662
  .optional()
499
663
  .nullable()
500
664
  .describe('Search First Agent'),
501
- clientId: zod_1.z.string().uuid().optional().nullable().describe('Search Client'),
502
- companyId: zod_1.z.string().uuid().optional().nullable().describe('Search Company'),
503
665
  location: common_schemas_1.LocationFilterSchema.optional()
504
666
  .nullable()
505
667
  .describe('Filter by location'),
506
668
  pay: common_schemas_1.PayRangeSchema.optional()
507
669
  .nullable()
508
670
  .describe('Filter by pay rate range'),
671
+ qualificationFilters: zod_1.z
672
+ .array(common_schemas_1.QualificationFilterSchema)
673
+ .optional()
674
+ .describe('Qualifications'),
509
675
  createdAt: common_schemas_1.DateRangeSchema.optional()
510
676
  .nullable()
511
677
  .describe('Filter by created date range'),
512
678
  updatedAt: common_schemas_1.DateRangeSchema.optional()
513
679
  .nullable()
514
680
  .describe('Filter by updated date range'),
515
- qualificationFilters: zod_1.z
516
- .array(curated_workers_contract_1.QualificationFilterSchema)
517
- .optional()
518
- .describe('Filter by qualifications'),
519
681
  });
520
682
  /**
521
683
  * Search Job Schema - For trigram-based duplicate detection
@@ -525,12 +687,15 @@ exports.SearchJobQuerySchema = zod_1.z
525
687
  description: zod_1.z
526
688
  .string()
527
689
  .min(10)
528
- .describe('Job description to search for similar jobs'),
529
- userId: zod_1.z
690
+ .describe('Description to search for similar jobs'),
691
+ userId: zod_1.z.string().uuid().optional().describe('Search First Agent'),
692
+ tradeId: zod_1.z.string().uuid().optional().describe('Trade'),
693
+ postcode: zod_1.z
530
694
  .string()
531
- .uuid()
695
+ .min(1)
696
+ .max(8)
532
697
  .optional()
533
- .describe('Filter by user who created the job'),
698
+ .describe('Postcode for structured fallback when trigram finds no matches'),
534
699
  threshold: zod_1.z.coerce
535
700
  .number()
536
701
  .min(0.1)
@@ -544,11 +709,28 @@ exports.SearchJobResultSchema = zod_1.z
544
709
  .object({
545
710
  similarity: zod_1.z.number().describe('Similarity score (0-1)'),
546
711
  job: exports.JobSchema.describe('The matching job'),
712
+ lastCloseSource: exports.JobCloseSourceSchema.nullable()
713
+ .optional()
714
+ .describe('closeSource of the last close event, when job is NOT_AVAILABLE'),
715
+ lastClosedAt: zod_1.z
716
+ .string()
717
+ .datetime()
718
+ .nullable()
719
+ .optional()
720
+ .describe('occurredAt of the last close event, when job is NOT_AVAILABLE'),
547
721
  })
548
722
  .openapi({ title: 'SearchJobResult' });
549
723
  exports.SearchJobResponseSchema = zod_1.z
550
724
  .array(exports.SearchJobResultSchema)
551
725
  .openapi({ title: 'SearchJobResponse' });
726
+ exports.DuplicateJobConflictSchema = zod_1.z
727
+ .object({
728
+ code: zod_1.z.literal('DUPLICATE_JOB_SUSPECTED'),
729
+ candidates: zod_1.z
730
+ .array(exports.SearchJobResultSchema)
731
+ .describe('Existing open jobs that look like duplicates of the submission'),
732
+ })
733
+ .openapi({ title: 'DuplicateJobConflict' });
552
734
  const c = (0, core_1.initContract)();
553
735
  exports.jobsContractRouter = c.router({
554
736
  create: {
@@ -556,28 +738,17 @@ exports.jobsContractRouter = c.router({
556
738
  path: '/v2/jobs',
557
739
  responses: {
558
740
  201: exports.JobSchema,
559
- 409: error_schemas_1.ErrorResponseSchema,
741
+ 409: exports.DuplicateJobConflictSchema,
560
742
  },
561
743
  body: exports.CreateJobSchema,
562
744
  summary: 'Create a new job',
563
745
  metadata: { tags: ['Jobs'], openApi: { operationId: 'createJob' } },
564
746
  },
565
- createDraft: {
566
- method: 'POST',
567
- path: '/v2/jobs/draft',
568
- responses: {
569
- 201: exports.JobSchema,
570
- 409: error_schemas_1.ErrorResponseSchema,
571
- },
572
- body: exports.CreateDraftJobSchema,
573
- summary: 'Create a draft job (without collaboration)',
574
- metadata: { tags: ['Jobs'], openApi: { operationId: 'createDraftJob' } },
575
- },
576
747
  findAll: {
577
748
  method: 'GET',
578
749
  path: '/v2/jobs',
579
750
  responses: {
580
- 200: exports.PaginatedJobResponseSchema,
751
+ 200: exports.PaginatedJobListResponseSchema,
581
752
  },
582
753
  query: exports.FilterJobSchema,
583
754
  summary: 'Get all jobs',
@@ -606,6 +777,25 @@ exports.jobsContractRouter = c.router({
606
777
  openApi: { operationId: 'getJobMapMarkers' },
607
778
  },
608
779
  },
780
+ getDemandBreakdown: {
781
+ method: 'GET',
782
+ path: '/v2/jobs/demand-breakdown',
783
+ responses: { 200: exports.DemandBreakdownResponseSchema },
784
+ query: exports.DemandBreakdownFilterSchema,
785
+ summary: 'Area×trade demand rollup: units/flow, stock, trend halves, centroids',
786
+ metadata: { tags: ['Jobs'], openApi: { operationId: 'getDemandBreakdown' } },
787
+ },
788
+ getDemandBreakdownDetail: {
789
+ method: 'GET',
790
+ path: '/v2/jobs/demand-breakdown/detail',
791
+ responses: { 200: exports.DemandBreakdownDetailResponseSchema },
792
+ query: exports.DemandBreakdownDetailQuerySchema,
793
+ summary: 'Evidence drill-down: demand units with episodes for one area×trade',
794
+ metadata: {
795
+ tags: ['Jobs'],
796
+ openApi: { operationId: 'getDemandBreakdownDetail' },
797
+ },
798
+ },
609
799
  batchUpdate: {
610
800
  method: 'PATCH',
611
801
  path: '/v2/jobs/batch',
@@ -639,6 +829,16 @@ exports.jobsContractRouter = c.router({
639
829
  openApi: { operationId: 'batchDeleteJobs' },
640
830
  },
641
831
  },
832
+ feed: {
833
+ method: 'GET',
834
+ path: '/v2/jobs/feed',
835
+ query: exports.JobFeedQuerySchema,
836
+ responses: {
837
+ 200: exports.JobFeedResponseSchema,
838
+ },
839
+ summary: 'Get a paginated live jobs feed; AVAILABLE jobs are retained and unavailable jobs expire after 30 minutes',
840
+ metadata: { tags: ['Jobs'], openApi: { operationId: 'getJobFeed' } },
841
+ },
642
842
  findOne: {
643
843
  method: 'GET',
644
844
  path: '/v2/jobs/:id',
@@ -652,6 +852,19 @@ exports.jobsContractRouter = c.router({
652
852
  summary: 'Get a job by ID',
653
853
  metadata: { tags: ['Jobs'], openApi: { operationId: 'findJobById' } },
654
854
  },
855
+ events: {
856
+ method: 'GET',
857
+ path: '/v2/jobs/:id/events',
858
+ responses: {
859
+ 200: zod_1.z.object({ items: exports.JobEventSchema.array() }),
860
+ 404: error_schemas_1.ErrorResponseSchema,
861
+ },
862
+ pathParams: zod_1.z.object({
863
+ id: zod_1.z.string().uuid().describe('Job ID'),
864
+ }),
865
+ summary: 'Get the lifecycle event history for a job (newest first)',
866
+ metadata: { tags: ['Jobs'], openApi: { operationId: 'getJobEvents' } },
867
+ },
655
868
  update: {
656
869
  method: 'PATCH',
657
870
  path: '/v2/jobs/:id',