wood-fired-tasks 1.12.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 (553) hide show
  1. package/AGENTS.md +112 -0
  2. package/CHANGELOG.md +271 -0
  3. package/CLAUDE.md +21 -0
  4. package/LICENSE +21 -0
  5. package/README.md +687 -0
  6. package/SECURITY.md +299 -0
  7. package/dist/api/hooks/error-handler.d.ts +6 -0
  8. package/dist/api/hooks/error-handler.js +128 -0
  9. package/dist/api/hooks/error-handler.js.map +1 -0
  10. package/dist/api/plugins/auth/index.d.ts +78 -0
  11. package/dist/api/plugins/auth/index.js +300 -0
  12. package/dist/api/plugins/auth/index.js.map +1 -0
  13. package/dist/api/plugins/auth/keys.d.ts +23 -0
  14. package/dist/api/plugins/auth/keys.js +100 -0
  15. package/dist/api/plugins/auth/keys.js.map +1 -0
  16. package/dist/api/plugins/auth/strategies/legacy.d.ts +46 -0
  17. package/dist/api/plugins/auth/strategies/legacy.js +87 -0
  18. package/dist/api/plugins/auth/strategies/legacy.js.map +1 -0
  19. package/dist/api/plugins/auth/strategies/pat.d.ts +37 -0
  20. package/dist/api/plugins/auth/strategies/pat.js +99 -0
  21. package/dist/api/plugins/auth/strategies/pat.js.map +1 -0
  22. package/dist/api/plugins/auth/strategies/session.d.ts +37 -0
  23. package/dist/api/plugins/auth/strategies/session.js +30 -0
  24. package/dist/api/plugins/auth/strategies/session.js.map +1 -0
  25. package/dist/api/plugins/auth/strategies/types.d.ts +12 -0
  26. package/dist/api/plugins/auth/strategies/types.js +2 -0
  27. package/dist/api/plugins/auth/strategies/types.js.map +1 -0
  28. package/dist/api/plugins/auth.d.ts +29 -0
  29. package/dist/api/plugins/auth.js +30 -0
  30. package/dist/api/plugins/auth.js.map +1 -0
  31. package/dist/api/plugins/swagger.d.ts +31 -0
  32. package/dist/api/plugins/swagger.js +83 -0
  33. package/dist/api/plugins/swagger.js.map +1 -0
  34. package/dist/api/routes/auth/auth-error.d.ts +23 -0
  35. package/dist/api/routes/auth/auth-error.js +68 -0
  36. package/dist/api/routes/auth/auth-error.js.map +1 -0
  37. package/dist/api/routes/auth/callback.d.ts +44 -0
  38. package/dist/api/routes/auth/callback.js +175 -0
  39. package/dist/api/routes/auth/callback.js.map +1 -0
  40. package/dist/api/routes/auth/csrf.d.ts +24 -0
  41. package/dist/api/routes/auth/csrf.js +75 -0
  42. package/dist/api/routes/auth/csrf.js.map +1 -0
  43. package/dist/api/routes/auth/device-code.d.ts +41 -0
  44. package/dist/api/routes/auth/device-code.js +51 -0
  45. package/dist/api/routes/auth/device-code.js.map +1 -0
  46. package/dist/api/routes/auth/device-disabled-stub.d.ts +33 -0
  47. package/dist/api/routes/auth/device-disabled-stub.js +16 -0
  48. package/dist/api/routes/auth/device-disabled-stub.js.map +1 -0
  49. package/dist/api/routes/auth/device-html.d.ts +41 -0
  50. package/dist/api/routes/auth/device-html.js +243 -0
  51. package/dist/api/routes/auth/device-html.js.map +1 -0
  52. package/dist/api/routes/auth/device-token.d.ts +38 -0
  53. package/dist/api/routes/auth/device-token.js +153 -0
  54. package/dist/api/routes/auth/device-token.js.map +1 -0
  55. package/dist/api/routes/auth/disabled-stub.d.ts +31 -0
  56. package/dist/api/routes/auth/disabled-stub.js +21 -0
  57. package/dist/api/routes/auth/disabled-stub.js.map +1 -0
  58. package/dist/api/routes/auth/index.d.ts +65 -0
  59. package/dist/api/routes/auth/index.js +47 -0
  60. package/dist/api/routes/auth/index.js.map +1 -0
  61. package/dist/api/routes/auth/login.d.ts +27 -0
  62. package/dist/api/routes/auth/login.js +91 -0
  63. package/dist/api/routes/auth/login.js.map +1 -0
  64. package/dist/api/routes/auth/logout.d.ts +29 -0
  65. package/dist/api/routes/auth/logout.js +43 -0
  66. package/dist/api/routes/auth/logout.js.map +1 -0
  67. package/dist/api/routes/comments/index.d.ts +3 -0
  68. package/dist/api/routes/comments/index.js +74 -0
  69. package/dist/api/routes/comments/index.js.map +1 -0
  70. package/dist/api/routes/comments/schemas.d.ts +37 -0
  71. package/dist/api/routes/comments/schemas.js +24 -0
  72. package/dist/api/routes/comments/schemas.js.map +1 -0
  73. package/dist/api/routes/dependencies/index.d.ts +3 -0
  74. package/dist/api/routes/dependencies/index.js +60 -0
  75. package/dist/api/routes/dependencies/index.js.map +1 -0
  76. package/dist/api/routes/dependencies/schemas.d.ts +24 -0
  77. package/dist/api/routes/dependencies/schemas.js +15 -0
  78. package/dist/api/routes/dependencies/schemas.js.map +1 -0
  79. package/dist/api/routes/events.d.ts +3 -0
  80. package/dist/api/routes/events.js +157 -0
  81. package/dist/api/routes/events.js.map +1 -0
  82. package/dist/api/routes/health.d.ts +27 -0
  83. package/dist/api/routes/health.js +231 -0
  84. package/dist/api/routes/health.js.map +1 -0
  85. package/dist/api/routes/me/index.d.ts +3 -0
  86. package/dist/api/routes/me/index.js +8 -0
  87. package/dist/api/routes/me/index.js.map +1 -0
  88. package/dist/api/routes/me/profile.d.ts +3 -0
  89. package/dist/api/routes/me/profile.js +58 -0
  90. package/dist/api/routes/me/profile.js.map +1 -0
  91. package/dist/api/routes/me/tokens.d.ts +3 -0
  92. package/dist/api/routes/me/tokens.js +410 -0
  93. package/dist/api/routes/me/tokens.js.map +1 -0
  94. package/dist/api/routes/projects/dependency-graph.d.ts +26 -0
  95. package/dist/api/routes/projects/dependency-graph.js +56 -0
  96. package/dist/api/routes/projects/dependency-graph.js.map +1 -0
  97. package/dist/api/routes/projects/index.d.ts +3 -0
  98. package/dist/api/routes/projects/index.js +96 -0
  99. package/dist/api/routes/projects/index.js.map +1 -0
  100. package/dist/api/routes/projects/schemas.d.ts +37 -0
  101. package/dist/api/routes/projects/schemas.js +27 -0
  102. package/dist/api/routes/projects/schemas.js.map +1 -0
  103. package/dist/api/routes/projects/topology.d.ts +27 -0
  104. package/dist/api/routes/projects/topology.js +51 -0
  105. package/dist/api/routes/projects/topology.js.map +1 -0
  106. package/dist/api/routes/tasks/index.d.ts +3 -0
  107. package/dist/api/routes/tasks/index.js +330 -0
  108. package/dist/api/routes/tasks/index.js.map +1 -0
  109. package/dist/api/routes/tasks/schemas.d.ts +316 -0
  110. package/dist/api/routes/tasks/schemas.js +129 -0
  111. package/dist/api/routes/tasks/schemas.js.map +1 -0
  112. package/dist/api/routes/web/index.d.ts +23 -0
  113. package/dist/api/routes/web/index.js +30 -0
  114. package/dist/api/routes/web/index.js.map +1 -0
  115. package/dist/api/routes/web/login.d.ts +20 -0
  116. package/dist/api/routes/web/login.js +20 -0
  117. package/dist/api/routes/web/login.js.map +1 -0
  118. package/dist/api/routes/web/me.d.ts +23 -0
  119. package/dist/api/routes/web/me.js +31 -0
  120. package/dist/api/routes/web/me.js.map +1 -0
  121. package/dist/api/routes/web/tokens.d.ts +29 -0
  122. package/dist/api/routes/web/tokens.js +65 -0
  123. package/dist/api/routes/web/tokens.js.map +1 -0
  124. package/dist/api/server.d.ts +44 -0
  125. package/dist/api/server.js +521 -0
  126. package/dist/api/server.js.map +1 -0
  127. package/dist/api/start.d.ts +1 -0
  128. package/dist/api/start.js +79 -0
  129. package/dist/api/start.js.map +1 -0
  130. package/dist/cli/api/client.d.ts +126 -0
  131. package/dist/cli/api/client.js +408 -0
  132. package/dist/cli/api/client.js.map +1 -0
  133. package/dist/cli/api/errors.d.ts +16 -0
  134. package/dist/cli/api/errors.js +20 -0
  135. package/dist/cli/api/errors.js.map +1 -0
  136. package/dist/cli/api/types.d.ts +205 -0
  137. package/dist/cli/api/types.js +15 -0
  138. package/dist/cli/api/types.js.map +1 -0
  139. package/dist/cli/auth/browser-open.d.ts +1 -0
  140. package/dist/cli/auth/browser-open.js +116 -0
  141. package/dist/cli/auth/browser-open.js.map +1 -0
  142. package/dist/cli/auth/credentials.d.ts +27 -0
  143. package/dist/cli/auth/credentials.js +179 -0
  144. package/dist/cli/auth/credentials.js.map +1 -0
  145. package/dist/cli/auth/device-flow.d.ts +75 -0
  146. package/dist/cli/auth/device-flow.js +149 -0
  147. package/dist/cli/auth/device-flow.js.map +1 -0
  148. package/dist/cli/bin/tasks-client.d.ts +2 -0
  149. package/dist/cli/bin/tasks-client.js +86 -0
  150. package/dist/cli/bin/tasks-client.js.map +1 -0
  151. package/dist/cli/bin/tasks.d.ts +3 -0
  152. package/dist/cli/bin/tasks.js +127 -0
  153. package/dist/cli/bin/tasks.js.map +1 -0
  154. package/dist/cli/commands/backup.d.ts +3 -0
  155. package/dist/cli/commands/backup.js +65 -0
  156. package/dist/cli/commands/backup.js.map +1 -0
  157. package/dist/cli/commands/claim.d.ts +2 -0
  158. package/dist/cli/commands/claim.js +37 -0
  159. package/dist/cli/commands/claim.js.map +1 -0
  160. package/dist/cli/commands/comment-add.d.ts +2 -0
  161. package/dist/cli/commands/comment-add.js +45 -0
  162. package/dist/cli/commands/comment-add.js.map +1 -0
  163. package/dist/cli/commands/comment-delete.d.ts +2 -0
  164. package/dist/cli/commands/comment-delete.js +56 -0
  165. package/dist/cli/commands/comment-delete.js.map +1 -0
  166. package/dist/cli/commands/comment-list.d.ts +2 -0
  167. package/dist/cli/commands/comment-list.js +56 -0
  168. package/dist/cli/commands/comment-list.js.map +1 -0
  169. package/dist/cli/commands/completed.d.ts +10 -0
  170. package/dist/cli/commands/completed.js +168 -0
  171. package/dist/cli/commands/completed.js.map +1 -0
  172. package/dist/cli/commands/completions.d.ts +10 -0
  173. package/dist/cli/commands/completions.js +179 -0
  174. package/dist/cli/commands/completions.js.map +1 -0
  175. package/dist/cli/commands/create.d.ts +2 -0
  176. package/dist/cli/commands/create.js +99 -0
  177. package/dist/cli/commands/create.js.map +1 -0
  178. package/dist/cli/commands/db-check.d.ts +3 -0
  179. package/dist/cli/commands/db-check.js +63 -0
  180. package/dist/cli/commands/db-check.js.map +1 -0
  181. package/dist/cli/commands/db-migrate-identities.d.ts +37 -0
  182. package/dist/cli/commands/db-migrate-identities.js +352 -0
  183. package/dist/cli/commands/db-migrate-identities.js.map +1 -0
  184. package/dist/cli/commands/db-mint-token.d.ts +33 -0
  185. package/dist/cli/commands/db-mint-token.js +150 -0
  186. package/dist/cli/commands/db-mint-token.js.map +1 -0
  187. package/dist/cli/commands/db.d.ts +10 -0
  188. package/dist/cli/commands/db.js +16 -0
  189. package/dist/cli/commands/db.js.map +1 -0
  190. package/dist/cli/commands/delete.d.ts +2 -0
  191. package/dist/cli/commands/delete.js +54 -0
  192. package/dist/cli/commands/delete.js.map +1 -0
  193. package/dist/cli/commands/dep-add.d.ts +2 -0
  194. package/dist/cli/commands/dep-add.js +43 -0
  195. package/dist/cli/commands/dep-add.js.map +1 -0
  196. package/dist/cli/commands/dep-list.d.ts +2 -0
  197. package/dist/cli/commands/dep-list.js +36 -0
  198. package/dist/cli/commands/dep-list.js.map +1 -0
  199. package/dist/cli/commands/dep-remove.d.ts +2 -0
  200. package/dist/cli/commands/dep-remove.js +55 -0
  201. package/dist/cli/commands/dep-remove.js.map +1 -0
  202. package/dist/cli/commands/doctor.d.ts +3 -0
  203. package/dist/cli/commands/doctor.js +139 -0
  204. package/dist/cli/commands/doctor.js.map +1 -0
  205. package/dist/cli/commands/health.d.ts +2 -0
  206. package/dist/cli/commands/health.js +28 -0
  207. package/dist/cli/commands/health.js.map +1 -0
  208. package/dist/cli/commands/list.d.ts +2 -0
  209. package/dist/cli/commands/list.js +103 -0
  210. package/dist/cli/commands/list.js.map +1 -0
  211. package/dist/cli/commands/login.d.ts +2 -0
  212. package/dist/cli/commands/login.js +210 -0
  213. package/dist/cli/commands/login.js.map +1 -0
  214. package/dist/cli/commands/logout.d.ts +31 -0
  215. package/dist/cli/commands/logout.js +184 -0
  216. package/dist/cli/commands/logout.js.map +1 -0
  217. package/dist/cli/commands/project-create.d.ts +2 -0
  218. package/dist/cli/commands/project-create.js +44 -0
  219. package/dist/cli/commands/project-create.js.map +1 -0
  220. package/dist/cli/commands/project-delete.d.ts +2 -0
  221. package/dist/cli/commands/project-delete.js +54 -0
  222. package/dist/cli/commands/project-delete.js.map +1 -0
  223. package/dist/cli/commands/project-list.d.ts +2 -0
  224. package/dist/cli/commands/project-list.js +55 -0
  225. package/dist/cli/commands/project-list.js.map +1 -0
  226. package/dist/cli/commands/project-show.d.ts +2 -0
  227. package/dist/cli/commands/project-show.js +38 -0
  228. package/dist/cli/commands/project-show.js.map +1 -0
  229. package/dist/cli/commands/project-update.d.ts +2 -0
  230. package/dist/cli/commands/project-update.js +56 -0
  231. package/dist/cli/commands/project-update.js.map +1 -0
  232. package/dist/cli/commands/show.d.ts +2 -0
  233. package/dist/cli/commands/show.js +38 -0
  234. package/dist/cli/commands/show.js.map +1 -0
  235. package/dist/cli/commands/stats.d.ts +3 -0
  236. package/dist/cli/commands/stats.js +81 -0
  237. package/dist/cli/commands/stats.js.map +1 -0
  238. package/dist/cli/commands/subtask-create.d.ts +2 -0
  239. package/dist/cli/commands/subtask-create.js +85 -0
  240. package/dist/cli/commands/subtask-create.js.map +1 -0
  241. package/dist/cli/commands/subtask-list.d.ts +2 -0
  242. package/dist/cli/commands/subtask-list.js +61 -0
  243. package/dist/cli/commands/subtask-list.js.map +1 -0
  244. package/dist/cli/commands/topology.d.ts +16 -0
  245. package/dist/cli/commands/topology.js +52 -0
  246. package/dist/cli/commands/topology.js.map +1 -0
  247. package/dist/cli/commands/update.d.ts +2 -0
  248. package/dist/cli/commands/update.js +90 -0
  249. package/dist/cli/commands/update.js.map +1 -0
  250. package/dist/cli/commands/whoami.d.ts +30 -0
  251. package/dist/cli/commands/whoami.js +201 -0
  252. package/dist/cli/commands/whoami.js.map +1 -0
  253. package/dist/cli/config/env.d.ts +4 -0
  254. package/dist/cli/config/env.js +25 -0
  255. package/dist/cli/config/env.js.map +1 -0
  256. package/dist/cli/output/error-handler.d.ts +5 -0
  257. package/dist/cli/output/error-handler.js +41 -0
  258. package/dist/cli/output/error-handler.js.map +1 -0
  259. package/dist/cli/output/formatters.d.ts +86 -0
  260. package/dist/cli/output/formatters.js +352 -0
  261. package/dist/cli/output/formatters.js.map +1 -0
  262. package/dist/cli/output/json-output.d.ts +39 -0
  263. package/dist/cli/output/json-output.js +50 -0
  264. package/dist/cli/output/json-output.js.map +1 -0
  265. package/dist/cli/output/spinner.d.ts +14 -0
  266. package/dist/cli/output/spinner.js +48 -0
  267. package/dist/cli/output/spinner.js.map +1 -0
  268. package/dist/cli/prompts/interactive.d.ts +25 -0
  269. package/dist/cli/prompts/interactive.js +80 -0
  270. package/dist/cli/prompts/interactive.js.map +1 -0
  271. package/dist/config/env.d.ts +182 -0
  272. package/dist/config/env.js +311 -0
  273. package/dist/config/env.js.map +1 -0
  274. package/dist/db/database.d.ts +11 -0
  275. package/dist/db/database.js +25 -0
  276. package/dist/db/database.js.map +1 -0
  277. package/dist/db/migrate.d.ts +10 -0
  278. package/dist/db/migrate.js +137 -0
  279. package/dist/db/migrate.js.map +1 -0
  280. package/dist/db/migrations/001-initial-schema.d.ts +3 -0
  281. package/dist/db/migrations/001-initial-schema.js +100 -0
  282. package/dist/db/migrations/001-initial-schema.js.map +1 -0
  283. package/dist/db/migrations/002-task-hierarchy-and-dependencies.d.ts +3 -0
  284. package/dist/db/migrations/002-task-hierarchy-and-dependencies.js +42 -0
  285. package/dist/db/migrations/002-task-hierarchy-and-dependencies.js.map +1 -0
  286. package/dist/db/migrations/003-comments-and-estimates.d.ts +3 -0
  287. package/dist/db/migrations/003-comments-and-estimates.js +36 -0
  288. package/dist/db/migrations/003-comments-and-estimates.js.map +1 -0
  289. package/dist/db/migrations/004-claim-protocol.d.ts +3 -0
  290. package/dist/db/migrations/004-claim-protocol.js +41 -0
  291. package/dist/db/migrations/004-claim-protocol.js.map +1 -0
  292. package/dist/db/migrations/005-backlogged-status.d.ts +3 -0
  293. package/dist/db/migrations/005-backlogged-status.js +156 -0
  294. package/dist/db/migrations/005-backlogged-status.js.map +1 -0
  295. package/dist/db/migrations/006-slack-channel-subscriptions.d.ts +3 -0
  296. package/dist/db/migrations/006-slack-channel-subscriptions.js +23 -0
  297. package/dist/db/migrations/006-slack-channel-subscriptions.js.map +1 -0
  298. package/dist/db/migrations/007-completed-at.d.ts +19 -0
  299. package/dist/db/migrations/007-completed-at.js +36 -0
  300. package/dist/db/migrations/007-completed-at.js.map +1 -0
  301. package/dist/db/migrations/008-identity-tables.d.ts +21 -0
  302. package/dist/db/migrations/008-identity-tables.js +84 -0
  303. package/dist/db/migrations/008-identity-tables.js.map +1 -0
  304. package/dist/db/migrations/009-parallel-fk-columns.d.ts +33 -0
  305. package/dist/db/migrations/009-parallel-fk-columns.js +62 -0
  306. package/dist/db/migrations/009-parallel-fk-columns.js.map +1 -0
  307. package/dist/db/migrations/010-identity-uniqueness-indexes.d.ts +47 -0
  308. package/dist/db/migrations/010-identity-uniqueness-indexes.js +65 -0
  309. package/dist/db/migrations/010-identity-uniqueness-indexes.js.map +1 -0
  310. package/dist/db/migrations/011-acceptance-criteria.d.ts +30 -0
  311. package/dist/db/migrations/011-acceptance-criteria.js +41 -0
  312. package/dist/db/migrations/011-acceptance-criteria.js.map +1 -0
  313. package/dist/db/migrations/012-verification-evidence.d.ts +41 -0
  314. package/dist/db/migrations/012-verification-evidence.js +49 -0
  315. package/dist/db/migrations/012-verification-evidence.js.map +1 -0
  316. package/dist/events/event-bus.d.ts +101 -0
  317. package/dist/events/event-bus.js +184 -0
  318. package/dist/events/event-bus.js.map +1 -0
  319. package/dist/events/sse-manager.d.ts +79 -0
  320. package/dist/events/sse-manager.js +220 -0
  321. package/dist/events/sse-manager.js.map +1 -0
  322. package/dist/events/types.d.ts +43 -0
  323. package/dist/events/types.js +22 -0
  324. package/dist/events/types.js.map +1 -0
  325. package/dist/index.d.ts +110 -0
  326. package/dist/index.js +209 -0
  327. package/dist/index.js.map +1 -0
  328. package/dist/lib/audit/schema.d.ts +201 -0
  329. package/dist/lib/audit/schema.js +141 -0
  330. package/dist/lib/audit/schema.js.map +1 -0
  331. package/dist/lib/decompose/schema.d.ts +157 -0
  332. package/dist/lib/decompose/schema.js +138 -0
  333. package/dist/lib/decompose/schema.js.map +1 -0
  334. package/dist/lib/loop-run/integration-audit-schema.d.ts +78 -0
  335. package/dist/lib/loop-run/integration-audit-schema.js +68 -0
  336. package/dist/lib/loop-run/integration-audit-schema.js.map +1 -0
  337. package/dist/lib/loop-run/schema.d.ts +49 -0
  338. package/dist/lib/loop-run/schema.js +67 -0
  339. package/dist/lib/loop-run/schema.js.map +1 -0
  340. package/dist/mcp/errors.d.ts +11 -0
  341. package/dist/mcp/errors.js +29 -0
  342. package/dist/mcp/errors.js.map +1 -0
  343. package/dist/mcp/identity-resolution.d.ts +76 -0
  344. package/dist/mcp/identity-resolution.js +189 -0
  345. package/dist/mcp/identity-resolution.js.map +1 -0
  346. package/dist/mcp/index.d.ts +1 -0
  347. package/dist/mcp/index.js +126 -0
  348. package/dist/mcp/index.js.map +1 -0
  349. package/dist/mcp/remote/index.d.ts +21 -0
  350. package/dist/mcp/remote/index.js +95 -0
  351. package/dist/mcp/remote/index.js.map +1 -0
  352. package/dist/mcp/remote/register-tools.d.ts +26 -0
  353. package/dist/mcp/remote/register-tools.js +751 -0
  354. package/dist/mcp/remote/register-tools.js.map +1 -0
  355. package/dist/mcp/remote/rest-client.d.ts +66 -0
  356. package/dist/mcp/remote/rest-client.js +300 -0
  357. package/dist/mcp/remote/rest-client.js.map +1 -0
  358. package/dist/mcp/resources/events.d.ts +28 -0
  359. package/dist/mcp/resources/events.js +98 -0
  360. package/dist/mcp/resources/events.js.map +1 -0
  361. package/dist/mcp/server.d.ts +59 -0
  362. package/dist/mcp/server.js +72 -0
  363. package/dist/mcp/server.js.map +1 -0
  364. package/dist/mcp/tools/comment-tools.d.ts +12 -0
  365. package/dist/mcp/tools/comment-tools.js +115 -0
  366. package/dist/mcp/tools/comment-tools.js.map +1 -0
  367. package/dist/mcp/tools/dependency-tools.d.ts +3 -0
  368. package/dist/mcp/tools/dependency-tools.js +91 -0
  369. package/dist/mcp/tools/dependency-tools.js.map +1 -0
  370. package/dist/mcp/tools/health-tools.d.ts +9 -0
  371. package/dist/mcp/tools/health-tools.js +82 -0
  372. package/dist/mcp/tools/health-tools.js.map +1 -0
  373. package/dist/mcp/tools/project-tools.d.ts +13 -0
  374. package/dist/mcp/tools/project-tools.js +167 -0
  375. package/dist/mcp/tools/project-tools.js.map +1 -0
  376. package/dist/mcp/tools/task-tools.d.ts +41 -0
  377. package/dist/mcp/tools/task-tools.js +434 -0
  378. package/dist/mcp/tools/task-tools.js.map +1 -0
  379. package/dist/mcp/tools/topology-tools.d.ts +14 -0
  380. package/dist/mcp/tools/topology-tools.js +46 -0
  381. package/dist/mcp/tools/topology-tools.js.map +1 -0
  382. package/dist/repositories/api-token.repository.d.ts +40 -0
  383. package/dist/repositories/api-token.repository.js +63 -0
  384. package/dist/repositories/api-token.repository.js.map +1 -0
  385. package/dist/repositories/comment.repository.d.ts +17 -0
  386. package/dist/repositories/comment.repository.js +73 -0
  387. package/dist/repositories/comment.repository.js.map +1 -0
  388. package/dist/repositories/dependency.repository.d.ts +19 -0
  389. package/dist/repositories/dependency.repository.js +55 -0
  390. package/dist/repositories/dependency.repository.js.map +1 -0
  391. package/dist/repositories/errors.d.ts +29 -0
  392. package/dist/repositories/errors.js +48 -0
  393. package/dist/repositories/errors.js.map +1 -0
  394. package/dist/repositories/interfaces.d.ts +200 -0
  395. package/dist/repositories/interfaces.js +2 -0
  396. package/dist/repositories/interfaces.js.map +1 -0
  397. package/dist/repositories/project.repository.d.ts +21 -0
  398. package/dist/repositories/project.repository.js +97 -0
  399. package/dist/repositories/project.repository.js.map +1 -0
  400. package/dist/repositories/row-mapper.d.ts +40 -0
  401. package/dist/repositories/row-mapper.js +38 -0
  402. package/dist/repositories/row-mapper.js.map +1 -0
  403. package/dist/repositories/task.repository.d.ts +45 -0
  404. package/dist/repositories/task.repository.js +612 -0
  405. package/dist/repositories/task.repository.js.map +1 -0
  406. package/dist/repositories/types.d.ts +20 -0
  407. package/dist/repositories/types.js +11 -0
  408. package/dist/repositories/types.js.map +1 -0
  409. package/dist/repositories/user.repository.d.ts +121 -0
  410. package/dist/repositories/user.repository.js +209 -0
  411. package/dist/repositories/user.repository.js.map +1 -0
  412. package/dist/schemas/comment.schema.d.ts +24 -0
  413. package/dist/schemas/comment.schema.js +27 -0
  414. package/dist/schemas/comment.schema.js.map +1 -0
  415. package/dist/schemas/dependency-graph.schema.d.ts +181 -0
  416. package/dist/schemas/dependency-graph.schema.js +98 -0
  417. package/dist/schemas/dependency-graph.schema.js.map +1 -0
  418. package/dist/schemas/dependency.schema.d.ts +9 -0
  419. package/dist/schemas/dependency.schema.js +16 -0
  420. package/dist/schemas/dependency.schema.js.map +1 -0
  421. package/dist/schemas/idempotency.schema.d.ts +18 -0
  422. package/dist/schemas/idempotency.schema.js +22 -0
  423. package/dist/schemas/idempotency.schema.js.map +1 -0
  424. package/dist/schemas/task.schema.d.ts +369 -0
  425. package/dist/schemas/task.schema.js +276 -0
  426. package/dist/schemas/task.schema.js.map +1 -0
  427. package/dist/schemas/topology.schema.d.ts +56 -0
  428. package/dist/schemas/topology.schema.js +48 -0
  429. package/dist/schemas/topology.schema.js.map +1 -0
  430. package/dist/services/auth-audit.d.ts +46 -0
  431. package/dist/services/auth-audit.js +28 -0
  432. package/dist/services/auth-audit.js.map +1 -0
  433. package/dist/services/claim-release.service.d.ts +42 -0
  434. package/dist/services/claim-release.service.js +90 -0
  435. package/dist/services/claim-release.service.js.map +1 -0
  436. package/dist/services/comment.service.d.ts +44 -0
  437. package/dist/services/comment.service.js +96 -0
  438. package/dist/services/comment.service.js.map +1 -0
  439. package/dist/services/dependency-graph.service.d.ts +33 -0
  440. package/dist/services/dependency-graph.service.js +453 -0
  441. package/dist/services/dependency-graph.service.js.map +1 -0
  442. package/dist/services/dependency.service.d.ts +32 -0
  443. package/dist/services/dependency.service.js +79 -0
  444. package/dist/services/dependency.service.js.map +1 -0
  445. package/dist/services/device-flow-store.d.ts +155 -0
  446. package/dist/services/device-flow-store.js +323 -0
  447. package/dist/services/device-flow-store.js.map +1 -0
  448. package/dist/services/errors.d.ts +28 -0
  449. package/dist/services/errors.js +44 -0
  450. package/dist/services/errors.js.map +1 -0
  451. package/dist/services/idempotency.service.d.ts +37 -0
  452. package/dist/services/idempotency.service.js +54 -0
  453. package/dist/services/idempotency.service.js.map +1 -0
  454. package/dist/services/identity-seeder.d.ts +56 -0
  455. package/dist/services/identity-seeder.js +131 -0
  456. package/dist/services/identity-seeder.js.map +1 -0
  457. package/dist/services/oidc-boot.d.ts +73 -0
  458. package/dist/services/oidc-boot.js +66 -0
  459. package/dist/services/oidc-boot.js.map +1 -0
  460. package/dist/services/oidc-client.d.ts +99 -0
  461. package/dist/services/oidc-client.js +108 -0
  462. package/dist/services/oidc-client.js.map +1 -0
  463. package/dist/services/pat-hash.d.ts +23 -0
  464. package/dist/services/pat-hash.js +73 -0
  465. package/dist/services/pat-hash.js.map +1 -0
  466. package/dist/services/pat-touch-debounce.d.ts +65 -0
  467. package/dist/services/pat-touch-debounce.js +82 -0
  468. package/dist/services/pat-touch-debounce.js.map +1 -0
  469. package/dist/services/project.service.d.ts +41 -0
  470. package/dist/services/project.service.js +133 -0
  471. package/dist/services/project.service.js.map +1 -0
  472. package/dist/services/slack.service.d.ts +31 -0
  473. package/dist/services/slack.service.js +52 -0
  474. package/dist/services/slack.service.js.map +1 -0
  475. package/dist/services/task.service.d.ts +151 -0
  476. package/dist/services/task.service.js +425 -0
  477. package/dist/services/task.service.js.map +1 -0
  478. package/dist/services/topology.service.d.ts +65 -0
  479. package/dist/services/topology.service.js +170 -0
  480. package/dist/services/topology.service.js.map +1 -0
  481. package/dist/services/user-upsert.d.ts +43 -0
  482. package/dist/services/user-upsert.js +53 -0
  483. package/dist/services/user-upsert.js.map +1 -0
  484. package/dist/services/workflow-engine.d.ts +93 -0
  485. package/dist/services/workflow-engine.js +250 -0
  486. package/dist/services/workflow-engine.js.map +1 -0
  487. package/dist/slack/commands/tasks-command.d.ts +88 -0
  488. package/dist/slack/commands/tasks-command.js +920 -0
  489. package/dist/slack/commands/tasks-command.js.map +1 -0
  490. package/dist/slack/formatters/project-formatter.d.ts +19 -0
  491. package/dist/slack/formatters/project-formatter.js +94 -0
  492. package/dist/slack/formatters/project-formatter.js.map +1 -0
  493. package/dist/slack/notifier.d.ts +41 -0
  494. package/dist/slack/notifier.js +111 -0
  495. package/dist/slack/notifier.js.map +1 -0
  496. package/dist/slack/repositories/channel-subscription.repository.d.ts +25 -0
  497. package/dist/slack/repositories/channel-subscription.repository.js +51 -0
  498. package/dist/slack/repositories/channel-subscription.repository.js.map +1 -0
  499. package/dist/slack/task-formatter.d.ts +31 -0
  500. package/dist/slack/task-formatter.js +151 -0
  501. package/dist/slack/task-formatter.js.map +1 -0
  502. package/dist/slack/user-identity.d.ts +37 -0
  503. package/dist/slack/user-identity.js +70 -0
  504. package/dist/slack/user-identity.js.map +1 -0
  505. package/dist/types/identity.d.ts +84 -0
  506. package/dist/types/identity.js +6 -0
  507. package/dist/types/identity.js.map +1 -0
  508. package/dist/types/task.d.ts +202 -0
  509. package/dist/types/task.js +17 -0
  510. package/dist/types/task.js.map +1 -0
  511. package/dist/utils/cycle-detector.d.ts +25 -0
  512. package/dist/utils/cycle-detector.js +86 -0
  513. package/dist/utils/cycle-detector.js.map +1 -0
  514. package/dist/utils/exit-codes.d.ts +64 -0
  515. package/dist/utils/exit-codes.js +57 -0
  516. package/dist/utils/exit-codes.js.map +1 -0
  517. package/dist/utils/is-main.d.ts +12 -0
  518. package/dist/utils/is-main.js +24 -0
  519. package/dist/utils/is-main.js.map +1 -0
  520. package/dist/utils/version.d.ts +1 -0
  521. package/dist/utils/version.js +22 -0
  522. package/dist/utils/version.js.map +1 -0
  523. package/dist/web/html.d.ts +73 -0
  524. package/dist/web/html.js +154 -0
  525. package/dist/web/html.js.map +1 -0
  526. package/dist/web/pages/device.d.ts +19 -0
  527. package/dist/web/pages/device.js +76 -0
  528. package/dist/web/pages/device.js.map +1 -0
  529. package/dist/web/pages/error.d.ts +6 -0
  530. package/dist/web/pages/error.js +23 -0
  531. package/dist/web/pages/error.js.map +1 -0
  532. package/dist/web/pages/login.d.ts +5 -0
  533. package/dist/web/pages/login.js +22 -0
  534. package/dist/web/pages/login.js.map +1 -0
  535. package/dist/web/pages/me.d.ts +9 -0
  536. package/dist/web/pages/me.js +37 -0
  537. package/dist/web/pages/me.js.map +1 -0
  538. package/dist/web/pages/tokens.d.ts +20 -0
  539. package/dist/web/pages/tokens.js +89 -0
  540. package/dist/web/pages/tokens.js.map +1 -0
  541. package/dist/web/session-constants.d.ts +21 -0
  542. package/dist/web/session-constants.js +22 -0
  543. package/dist/web/session-constants.js.map +1 -0
  544. package/dist/web/session-flash.d.ts +15 -0
  545. package/dist/web/session-flash.js +11 -0
  546. package/dist/web/session-flash.js.map +1 -0
  547. package/dist/web/session-user.d.ts +59 -0
  548. package/dist/web/session-user.js +44 -0
  549. package/dist/web/session-user.js.map +1 -0
  550. package/docs/AGENT_CONTEXT.md +280 -0
  551. package/docs/README.md +49 -0
  552. package/llms.txt +33 -0
  553. package/package.json +129 -0
package/README.md ADDED
@@ -0,0 +1,687 @@
1
+ # Wood Fired Tasks
2
+
3
+ [![CI](https://github.com/Wood-Fired-Games/wood-fired-tasks/actions/workflows/ci.yml/badge.svg)](https://github.com/Wood-Fired-Games/wood-fired-tasks/actions/workflows/ci.yml)
4
+ [![Install Scripts](https://github.com/Wood-Fired-Games/wood-fired-tasks/actions/workflows/install-scripts.yml/badge.svg)](https://github.com/Wood-Fired-Games/wood-fired-tasks/actions/workflows/install-scripts.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+
7
+ Open-source task tracking system from Wood Fired Games.
8
+
9
+ Wood Fired Tasks is a centralized task management service providing a REST API, CLI tool, and MCP server for managing work items across all projects. LLM agents interact via REST or MCP; humans interact via CLI. All three interfaces share a common service layer and SQLite database with full feature parity. Real-time SSE event streaming enables multi-agent coordination with atomic task claiming and workflow automation.
10
+
11
+ **Key capabilities:**
12
+
13
+ - REST API with 47 route handlers across `src/api/routes/` (1 public `/health`; the rest authenticated) for full task lifecycle management — a single running instance serves up to 40 of them (the OIDC-disabled `/auth/*` stub handlers are mutually exclusive with the live OIDC routes)
14
+ - CLI (`tasks`) with 31 commands for terminal-based operations
15
+ - MCP server with 22 tools for native Claude Code integration (local SQLite or remote HTTP modes)
16
+ - 16 task-loop skill files that ship as Claude Code slash commands today; the underlying recipes are vendor-neutral and any agent harness can consume them
17
+ - Real-time Server-Sent Events (SSE) for task change notifications
18
+ - Atomic task claiming with optimistic locking for multi-agent coordination
19
+ - Workflow automation: parent auto-complete and dependency auto-unblock
20
+ - SQLite database with WAL mode, FTS5 full-text search, and automatic migrations
21
+ - Cross-platform installers for Linux/macOS and Windows
22
+
23
+ ## For agents
24
+
25
+ Coding agents (Claude Code, Cursor, Gemini, Codex, and others) should start with:
26
+
27
+ 1. [AGENTS.md](AGENTS.md) — first-read navigation hub.
28
+ 2. [docs/AGENT_CONTEXT.md](docs/AGENT_CONTEXT.md) — the vendor-neutral context contract.
29
+ 3. [.agent-context.json](.agent-context.json) — machine-readable manifest of canonical files and their budgets.
30
+
31
+ Vendor-specific files (`CLAUDE.md`, `.cursor/`, `.gemini/`, `.codex/`) are adapters and MUST NOT carry unique facts — see `docs/AGENT_CONTEXT.md` §6.
32
+
33
+ ## Quick Start
34
+
35
+ ```bash
36
+ # Clone and install
37
+ git clone https://github.com/Wood-Fired-Games/wood-fired-tasks.git
38
+ cd wood-fired-tasks
39
+ npm install
40
+ npm run build
41
+
42
+ # Set environment variables
43
+ export API_KEYS="your-api-key-here"
44
+ export DATABASE_PATH="./data/tasks.db"
45
+
46
+ # Run database migrations
47
+ npm run migrate
48
+
49
+ # Start the API server
50
+ npm start
51
+
52
+ # Use the CLI
53
+ tasks list
54
+ tasks create --title "My first task" --project 1 --created-by "me"
55
+ ```
56
+
57
+ For detailed setup instructions, see [docs/SETUP.md](docs/SETUP.md).
58
+
59
+ ## Self-hosting
60
+
61
+ For self-hosted production deploys (including the fork-and-deploy workflow for OSS operators): provision a host once with `deploy/install.sh`, then ship every subsequent release in place with `deploy/upgrade.sh` (atomic backup, migrate, restart, `/health` probe, manual rollback recipe on failure). The full walkthrough — first-time install, in-place upgrades, deploying your fork, manual rollback, and the migration safety contract — lives at [Self-hosting and upgrades](docs/SETUP.md#self-hosting-and-upgrades). When a deploy or a reboot goes sideways, the [Troubleshooting & Recovery runbook](docs/TROUBLESHOOTING.md) covers boot failures (`exit 78`), wrong/stale-database symptoms, and safe backup/restore.
62
+
63
+ ## Security Model
64
+
65
+ **Read this before deploying.** Wood Fired Tasks is built for trusted multi-agent coordination. As of **v1.6** the REST API authenticates every `/api/v1` request through a three-strategy chain (`src/api/plugins/auth/index.ts`), tried in order — the first strategy that produces a valid user wins, and that user's id is stamped onto every write (`created_by_user_id`, `assignee_user_id`, …) and the per-request audit log (`user_id`, `token_id`, `auth_method`):
66
+
67
+ | Order | Strategy | Credential | Wire format |
68
+ |-------|----------|------------|-------------|
69
+ | 1 | **PAT** — recommended for machines/agents | row in `api_tokens` (SHA-256 hash stored) | `Authorization: Bearer wft_pat_<…>` |
70
+ | 2 | **Session** — recommended for humans | OIDC sign-in → sealed-box cookie | `Cookie: wft_session=<…>` |
71
+ | 3 | **Legacy** — deprecated but still supported (see below) | entry in `API_KEYS` env list | `X-API-Key: <…>` |
72
+
73
+ PATs are minted from a logged-in `/me` web session or offline via `tasks db mint-token`; the raw value is shown **once** at mint time (only a hash is stored) and revoked via the `/me` UI, `DELETE /me/tokens/:id`, or `tasks logout`. Sessions come from OIDC (`/auth/login` → provider → `/auth/callback`, protected by PKCE + state), are sealed-box-encrypted with `SESSION_COOKIE_SECRET`, and expire after 8h. The CLI and remote MCP client auto-select the header from the `wft_pat_` prefix, so the same env var accepts a PAT or a legacy key. Full detail: [SECURITY.md → Authentication Architecture](SECURITY.md#authentication-architecture).
74
+
75
+ ### ⚠️ Authentication is NOT authorization — every identity is admin
76
+
77
+ **Read this before exposing the service to anything but trusted callers.**
78
+
79
+ - **Authentication ≠ authorization.** The auth chain only *identifies* the caller; it does **not** scope what they may do.
80
+ - **Every authenticated identity is effectively an admin.** Any valid credential — PAT, OIDC session, or legacy `X-API-Key` — can read, write, and delete **every** task, project, comment, and dependency across **every** project in the database.
81
+ - **There is NO RBAC, NO ACL, and NO per-project / per-tenant isolation.** These are not implemented; scoped/role-based permissions are tracked only as future work.
82
+ - **Do NOT expose this service on a public network, and do NOT run it multi-tenant, without an external authorization layer** (e.g. an authenticating reverse proxy that enforces its own per-tenant access control in front of the API). Treat any issued credential as full admin access to all data.
83
+
84
+ ### Legacy `X-API-Key` is still supported (PAT / OIDC preferred)
85
+
86
+ The legacy `X-API-Key` strategy **still works today** — it is strategy #3 in the live auth chain (`src/api/plugins/auth/index.ts`), and `API_KEYS` is currently a **required** env var (see Configuration), so every deployment has at least one working key. It is marked **deprecated as of v1.6**: PAT and OIDC sessions are the preferred credentials going forward, but legacy keys have **not** been removed. Legacy-authed responses carry advisory RFC 8594 `Deprecation: true` + `Sunset: <LEGACY_AUTH_SUNSET_DATE>` headers (operator-controlled, default `2026-12-31`) and emit a `legacy_auth_used` warn log so operators can track migration progress. New deployments should issue **PATs** — one per machine/agent, so you can revoke an individual token without disturbing others — or use OIDC sessions. The `API_KEYS` env accepts a comma-separated list of `key` or `key:label` entries (the label surfaces in audit logs as `apiKeyLabel`; the raw key is never logged). See [SECURITY.md → Legacy Auth Sunset Timeline](SECURITY.md#legacy-auth-sunset-timeline) and `tasks db migrate-identities` for the planned migration path.
87
+
88
+ ### Defense in depth
89
+
90
+ Auth is paired with two configurable protections, both mitigations rather than authorization:
91
+
92
+ - **Rate limiting** via `@fastify/rate-limit` (global, 1000 req/min default) — tunable through `RATE_LIMIT_MAX` and `RATE_LIMIT_TIME_WINDOW`.
93
+ - **SSE connection caps** — per-key, per-IP, and global limits on long-lived event-stream connections (`SSE_MAX_CONNECTIONS_PER_KEY` / `SSE_MAX_CONNECTIONS_PER_IP` / `SSE_MAX_CONNECTIONS`).
94
+
95
+ These reduce blast radius; they do not substitute for credential hygiene. For incident response (credential compromise, rotation, disclosure), see [SECURITY.md](SECURITY.md).
96
+
97
+ ## Architecture
98
+
99
+ The service is a single Node process exposing three peer entry points
100
+ (REST, CLI, MCP) over a shared service layer, plus an optional Slack
101
+ subprocess that reuses the same services and database. Real-time events
102
+ flow through an in-process EventBus to the SSE Manager (browser/agent
103
+ consumers) and the Slack notifier (channel subscribers).
104
+
105
+ ```mermaid
106
+ flowchart TB
107
+ subgraph clients[Clients]
108
+ HumanCLI[Terminal user<br/>tasks CLI]
109
+ HTTPAgent[HTTP / SSE agent]
110
+ ClaudeMCP[Claude Code<br/>MCP stdio]
111
+ SlackUser[Slack user<br/>/tasks slash]
112
+ end
113
+
114
+ subgraph entry[Entry points]
115
+ CLI[CLI<br/>Commander.js]
116
+ REST[REST API<br/>Fastify :3000]
117
+ MCP[MCP Server<br/>stdio + remote HTTP]
118
+ Slack[Slack subprocess<br/>@slack/bolt]
119
+ end
120
+
121
+ subgraph guards[Auth and validation]
122
+ Auth[auth plugin<br/>X-API-Key]
123
+ RL[Rate limiter<br/>RATE_LIMIT_*]
124
+ Zod[Zod schemas<br/>request/response]
125
+ end
126
+
127
+ subgraph core[Service layer - shared]
128
+ TS[TaskService]
129
+ PS[ProjectService]
130
+ DS[DependencyService]
131
+ CS[CommentService]
132
+ Workflow[Workflow Engine<br/>cascade: parent auto-complete,<br/>dependency auto-unblock,<br/>depth-limited]
133
+ Idem[Idempotency Service]
134
+ Claim[Claim/Release Service]
135
+ end
136
+
137
+ subgraph events[Events]
138
+ Bus[EventBus<br/>in-process]
139
+ SSE[SSE Manager<br/>per-key/IP/global caps]
140
+ Notifier[Slack Notifier<br/>per-channel retry]
141
+ end
142
+
143
+ subgraph storage[Persistence]
144
+ DB[(SQLite WAL<br/>tasks, projects, task_comments,<br/>task_dependencies, idempotency_keys,<br/>slack_channel_subscriptions)]
145
+ Subs[(Channel<br/>Subscription Repo)]
146
+ end
147
+
148
+ HumanCLI --> CLI
149
+ HTTPAgent -->|HTTP + X-API-Key| REST
150
+ ClaudeMCP -->|stdio JSON-RPC| MCP
151
+ SlackUser -->|Socket Mode| Slack
152
+
153
+ CLI -->|HTTP| REST
154
+ REST --> Auth --> RL --> Zod --> TS
155
+ Zod --> PS
156
+ Zod --> DS
157
+ Zod --> CS
158
+ MCP --> TS
159
+ MCP --> PS
160
+ MCP --> DS
161
+ MCP --> CS
162
+ Slack --> TS
163
+ Slack --> PS
164
+ Slack --> DS
165
+ Slack --> CS
166
+ Slack --> Subs
167
+
168
+ TS --> Workflow
169
+ TS --> Claim
170
+ Claim --> Idem
171
+ Workflow --> Bus
172
+ TS --> Bus
173
+ PS --> Bus
174
+ DS --> Bus
175
+ CS --> Bus
176
+
177
+ Bus --> SSE
178
+ Bus --> Notifier
179
+ Notifier --> Subs
180
+ SSE -->|text/event-stream| HTTPAgent
181
+ Notifier -->|chat.postMessage| SlackUser
182
+
183
+ TS --> DB
184
+ PS --> DB
185
+ DS --> DB
186
+ CS --> DB
187
+ Claim --> DB
188
+ Subs --> DB
189
+ ```
190
+
191
+ | Interface | Access Method | Transport | Auth |
192
+ |-----------|--------------|-----------|------|
193
+ | REST API | HTTP endpoints | Port 3000 (configurable) | PAT (`Authorization: Bearer`), session cookie, or legacy `X-API-Key` |
194
+ | CLI | `tasks` command | HTTP to API server (most cmds); direct SQLite for offline ops (`backup`, `doctor`, `stats`, `db-check`, `completed`) | `API_KEY` env var (accepts a PAT or legacy key) |
195
+ | MCP Server | stdio JSON-RPC (local) or HTTP (remote variant) | MCP client integration | None for stdio (local access); Bearer PAT or `X-API-Key` for remote |
196
+ | Slack subprocess | Slack Socket Mode | WebSocket to Slack | Slack signing secret + bot token |
197
+
198
+ All entry points share the same TypeScript services
199
+ (TaskService, ProjectService, DependencyService, CommentService), the
200
+ Workflow Engine (cascades parent auto-complete and dependency
201
+ auto-unblock; depth-limited and wrapped in a transaction), and the same
202
+ SQLite database in WAL mode. The Slack notifier is a downstream
203
+ EventBus subscriber — it never blocks task mutations, retries transient
204
+ errors twice, and short-circuits permanent errors
205
+ (`not_in_channel`, `channel_not_found`, `invalid_auth`, `token_revoked`).
206
+
207
+ ## Data Model
208
+
209
+ ### Entities
210
+
211
+ | Entity | Key Fields |
212
+ |--------|------------|
213
+ | **projects** | id, name, description, created_at, updated_at |
214
+ | **tasks** | id, title, description, status, priority, project_id, parent_task_id, estimated_minutes, assignee, created_by, due_date, version, claimed_at, **completed_at**, created_at, updated_at |
215
+ | **task_tags** | id, task_id, tag |
216
+ | **task_dependencies** | id, task_id, blocks_task_id, created_at |
217
+ | **task_comments** | id, task_id, author, content, created_at, updated_at |
218
+ | **idempotency_keys** | key, response, created_at |
219
+ | **slack_channel_subscriptions** | id, channel_id, project_id, event_type, created_at (UNIQUE on the triple) |
220
+ | **users** | id, oidc_sub, oidc_provider, email, display_name, slack_user_id, is_legacy, is_service_account, created_at, disabled_at |
221
+ | **api_tokens** | id, user_id, name, prefix, suffix, hash, scopes, created_at, last_used_at, revoked_at, expires_at |
222
+
223
+ ### Task Statuses
224
+
225
+ Valid statuses: `open`, `in_progress`, `done`, `closed`, `blocked`, `backlogged`
226
+
227
+ - `backlogged` is "deferred but not abandoned" — distinct from `closed` (won't-do / archive).
228
+ - `completed_at` is populated only when a task transitions **into** `done`,
229
+ and cleared if it transitions back out (e.g. `done → open`). `closed` is
230
+ intentionally not treated as completion (separate terminal state).
231
+
232
+ ### Task Priorities
233
+
234
+ Valid priorities: `low`, `medium`, `high`, `urgent`
235
+
236
+ ### Status Transitions
237
+
238
+ | From Status | Allowed Transitions |
239
+ |-------------|---------------------|
240
+ | open | in_progress, blocked, closed, backlogged |
241
+ | in_progress | done, blocked, open |
242
+ | blocked | open, in_progress |
243
+ | backlogged | open |
244
+ | done | closed, open |
245
+ | closed | open |
246
+
247
+ (Canonical source: `VALID_STATUS_TRANSITIONS` in [`src/types/task.ts`](src/types/task.ts).)
248
+
249
+ ## API Summary
250
+
251
+ All `/api/v1` endpoints require authentication — a PAT (`Authorization: Bearer wft_pat_…`), an OIDC session cookie, or a legacy `X-API-Key` header (deprecated). `GET /health` is public; the OIDC sign-in flow lives under `/auth/*` (outside `/api/v1`).
252
+
253
+ Base URL: `http://localhost:3000`
254
+
255
+ ### Health
256
+
257
+ | Method | Path | Description |
258
+ |--------|------|-------------|
259
+ | GET | /health | Minimal public liveness check — returns only `{ status, timestamp, version }` (no auth required). Pings the DB and returns 503 in the same shape on failure; intentionally leaks no deployment fingerprint. |
260
+ | GET | /health/detailed | Authenticated diagnostic check — adds resolved DB path/fingerprint, component checks (database, eventBus, sseManager, oidc), OIDC discovery detail, and runtime stats. |
261
+
262
+ ### Projects
263
+
264
+ | Method | Path | Description |
265
+ |--------|------|-------------|
266
+ | POST | /api/v1/projects | Create a new project |
267
+ | GET | /api/v1/projects | List all projects |
268
+ | GET | /api/v1/projects/:id | Get project by ID |
269
+ | PUT | /api/v1/projects/:id | Update project |
270
+ | DELETE | /api/v1/projects/:id | Delete project |
271
+ | GET | /api/v1/projects/:id/topology | Classify the project's dependency graph (FLAT / DAG / DAG_CYCLIC) |
272
+ | GET | /api/v1/projects/:id/dependency-graph | Dashboard tree-view of the project's task dependency graph |
273
+
274
+ ### Tasks
275
+
276
+ | Method | Path | Description |
277
+ |--------|------|-------------|
278
+ | POST | /api/v1/tasks | Create a new task |
279
+ | GET | /api/v1/tasks | List tasks with filters |
280
+ | GET | /api/v1/tasks/completion-report | Completion dashboard for a time window (per-project/assignee/priority aggregates) |
281
+ | GET | /api/v1/tasks/:id | Get task by ID |
282
+ | PUT | /api/v1/tasks/:id | Update task |
283
+ | DELETE | /api/v1/tasks/:id | Delete task |
284
+ | POST | /api/v1/tasks/:id/claim | Atomically claim an unassigned task |
285
+ | GET | /api/v1/tasks/:id/subtasks | Get subtasks of a task |
286
+
287
+ ### Comments
288
+
289
+ | Method | Path | Description |
290
+ |--------|------|-------------|
291
+ | POST | /api/v1/tasks/:id/comments | Add comment to task |
292
+ | GET | /api/v1/tasks/:id/comments | List comments for task |
293
+ | DELETE | /api/v1/tasks/:id/comments/:commentId | Delete comment |
294
+
295
+ ### Dependencies
296
+
297
+ | Method | Path | Description |
298
+ |--------|------|-------------|
299
+ | POST | /api/v1/tasks/:id/dependencies | Add dependency (this task blocks another) |
300
+ | GET | /api/v1/tasks/:id/dependencies | Get dependencies for task |
301
+ | DELETE | /api/v1/tasks/:id/dependencies/:blocksTaskId | Remove dependency |
302
+
303
+ ### Events
304
+
305
+ | Method | Path | Description |
306
+ |--------|------|-------------|
307
+ | GET | /api/v1/events | Subscribe to real-time SSE event stream |
308
+
309
+ ### Authentication & Identity
310
+
311
+ The OIDC/session/PAT surface backing the auth model lives partly outside the task API:
312
+
313
+ | Method | Path | Description |
314
+ |--------|------|-------------|
315
+ | GET | /auth/login | Begin OIDC sign-in (redirects to provider; PKCE + state) |
316
+ | GET | /auth/callback | OIDC redirect callback → sets the session cookie |
317
+ | POST | /auth/logout | Revoke the active PAT and clear the session |
318
+ | GET | /auth/error | OIDC/session error landing page (session-expiry, 403 destinations) |
319
+ | GET | /api/v1/me | Current authenticated user's profile (accepts session, PAT, or legacy auth) |
320
+ | GET | /api/v1/me/tokens | List the caller's personal access tokens |
321
+ | DELETE | /api/v1/me/tokens/active | Revoke the caller's currently-active token |
322
+ | DELETE | /api/v1/me/tokens/:id | Revoke a personal access token by ID |
323
+
324
+ A device-authorization flow under `/auth/device*` (`GET /auth/device`, `POST /auth/device/code`, `POST /auth/device/token`, `POST /auth/device/verify`) supports headless PAT minting. When OIDC is **not** configured, the `/auth/*` and `/auth/device/*` routes are replaced by disabled-stub handlers (HTTP 501), so they exist in both modes but only one set is live per instance. When `SESSION_COOKIE_SECRET` is set, top-level HTML web routes (`GET /login`, `GET /me`, `GET /me/tokens`, `POST /me/tokens/:id/revoke`) are also served for the browser sign-in UI.
325
+
326
+ This brings the full registered surface to **47 route handlers** under `src/api/routes/` — derived by counting `fastify.<verb>(` / `server.<verb>(` registrations across the route files (excluding tests). A single running instance serves up to **40** of them: the 7 OIDC-disabled stub handlers are mutually exclusive with the 8 live OIDC `/auth/*` routes.
327
+
328
+ For detailed API documentation including request/response schemas, see [docs/API.md](docs/API.md).
329
+
330
+ ## CLI Summary
331
+
332
+ The `tasks` command provides terminal access to all task operations.
333
+
334
+ **Global Flags:**
335
+ - `--json` - Output in machine-readable JSON format
336
+ - `--no-input` - Disable interactive prompts
337
+ - `--force` - Skip confirmation prompts
338
+
339
+ ### Task Commands
340
+
341
+ | Command | Description |
342
+ |---------|-------------|
343
+ | tasks create | Create a new task (interactive or with options) |
344
+ | tasks list | List tasks with filters |
345
+ | tasks show \<id\> | Show task details |
346
+ | tasks update \<id\> | Update task fields |
347
+ | tasks delete \<id\> | Delete a task |
348
+ | tasks claim \<id\> | Atomically claim an unassigned task |
349
+
350
+ ### Project Commands
351
+
352
+ | Command | Description |
353
+ |---------|-------------|
354
+ | tasks project-create | Create a new project |
355
+ | tasks project-list | List all projects |
356
+ | tasks project-show \<id\> | Show project details |
357
+ | tasks project-update \<id\> | Update project |
358
+ | tasks project-delete \<id\> | Delete project |
359
+
360
+ ### Dependency Commands
361
+
362
+ | Command | Description |
363
+ |---------|-------------|
364
+ | tasks dep-add \<taskId\> \<blocksTaskId\> | Add dependency relationship |
365
+ | tasks dep-remove \<taskId\> \<blocksTaskId\> | Remove dependency |
366
+ | tasks dep-list \<taskId\> | List dependencies for task |
367
+ | tasks topology \<projectId\> | Classify a project's dependency graph (FLAT / DAG / DAG_CYCLIC) |
368
+
369
+ ### Comment Commands
370
+
371
+ | Command | Description |
372
+ |---------|-------------|
373
+ | tasks comment-add \<taskId\> | Add comment to task |
374
+ | tasks comment-list \<taskId\> | List comments for task |
375
+ | tasks comment-delete \<commentId\> | Delete comment |
376
+
377
+ ### Subtask Commands
378
+
379
+ | Command | Description |
380
+ |---------|-------------|
381
+ | tasks subtask-create \<parentTaskId\> | Create a subtask |
382
+ | tasks subtask-list \<parentTaskId\> | List subtasks |
383
+
384
+ ### Health
385
+
386
+ | Command | Description |
387
+ |---------|-------------|
388
+ | tasks health | Check server health |
389
+
390
+ ### Authentication Commands
391
+
392
+ | Command | Description |
393
+ |---------|-------------|
394
+ | tasks login | OIDC sign-in; caches a PAT to the local credentials file |
395
+ | tasks logout | Revoke the active PAT and clear the local credentials |
396
+ | tasks whoami | Show the currently authenticated identity |
397
+
398
+ ### Admin & Offline Commands
399
+
400
+ These talk to SQLite directly (no running server required):
401
+
402
+ | Command | Description |
403
+ |---------|-------------|
404
+ | tasks backup | Back up the SQLite database to a file |
405
+ | tasks doctor | Diagnose database / config health |
406
+ | tasks stats | Show task / project statistics |
407
+ | tasks completed | List recently completed tasks |
408
+ | tasks db-check | Verify the database schema / integrity |
409
+ | tasks db mint-token | Mint a PAT offline (`--user`, `--name`, optional `--expires-at`) |
410
+ | tasks db migrate-identities | Backfill identity FK columns (preparation for the legacy-auth migration path) |
411
+ | tasks completions | Generate shell completion scripts |
412
+
413
+ For detailed CLI documentation including all options and examples, see [docs/CLI.md](docs/CLI.md).
414
+
415
+ ## MCP Tools Summary
416
+
417
+ The MCP server exposes 22 tools and 1 resource for Claude Code integration. A second entry point (`npm run mcp:remote`) exposes the full REST-backed tool surface (22 tools, at parity with local) for clients running on a different host than the bugs API — see [docs/MCP.md#remote-mcp-server](docs/MCP.md#remote-mcp-server).
418
+
419
+ ### Task Tools (9)
420
+
421
+ | Tool | Description |
422
+ |------|-------------|
423
+ | create_task | Create a new task in a project |
424
+ | get_task | Get a task by its ID |
425
+ | update_task | Update an existing task |
426
+ | list_tasks | List tasks with optional filters and pagination |
427
+ | delete_task | Delete a task by its ID |
428
+ | claim_task | Atomically claim an unassigned task |
429
+ | list_subtasks | Paginated list of subtasks for a parent task |
430
+ | get_subtasks | Paginated subtasks for a parent task (alternative shape) |
431
+ | completion_report | Dashboard of tasks completed in a window with per-project/assignee/priority aggregates |
432
+
433
+ ### Project Tools (5)
434
+
435
+ | Tool | Description |
436
+ |------|-------------|
437
+ | create_project | Create a new project |
438
+ | get_project | Get a project by its ID |
439
+ | list_projects | List all projects |
440
+ | update_project | Update an existing project |
441
+ | delete_project | Delete a project by its ID |
442
+
443
+ ### Comment Tools (3)
444
+
445
+ | Tool | Description |
446
+ |------|-------------|
447
+ | add_comment | Add a comment to a task |
448
+ | get_comments | Get all comments for a task |
449
+ | delete_comment | Delete a comment by ID |
450
+
451
+ ### Dependency Tools (3)
452
+
453
+ | Tool | Description |
454
+ |------|-------------|
455
+ | add_dependency | Add a dependency relationship between tasks |
456
+ | remove_dependency | Remove a dependency relationship |
457
+ | get_dependencies | Get all dependencies for a task |
458
+
459
+ ### Health Tools (1)
460
+
461
+ | Tool | Description |
462
+ |------|-------------|
463
+ | check_health | Check service health status |
464
+
465
+ ### Topology Tools (1)
466
+
467
+ | Tool | Description |
468
+ |------|-------------|
469
+ | topology_check | Classify a project's dependency graph as FLAT / DAG / DAG_CYCLIC |
470
+
471
+ ### Resources (1)
472
+
473
+ | URI | Description |
474
+ |-----|-------------|
475
+ | events://stream | SSE event stream discovery documentation |
476
+
477
+ For detailed MCP documentation including tool schemas and Claude Code skill files, see [docs/MCP.md](docs/MCP.md).
478
+
479
+ ## Real-Time Events
480
+
481
+ Wood Fired Tasks streams real-time task and project change notifications via Server-Sent Events (SSE).
482
+
483
+ ### Event Types
484
+
485
+ | Event | Trigger |
486
+ |-------|---------|
487
+ | task.created | New task created |
488
+ | task.updated | Task fields modified |
489
+ | task.deleted | Task deleted |
490
+ | task.status_changed | Task status transition |
491
+ | task.claimed | Task claimed by agent |
492
+ | project.created | New project created |
493
+ | project.updated | Project modified |
494
+ | project.deleted | Project deleted |
495
+
496
+ ### Subscribing
497
+
498
+ ```bash
499
+ # Subscribe to all events
500
+ curl -N -H "X-API-Key: your-key" \
501
+ http://localhost:3000/api/v1/events
502
+
503
+ # Filter by project
504
+ curl -N -H "X-API-Key: your-key" \
505
+ "http://localhost:3000/api/v1/events?project_id=1"
506
+
507
+ # Filter by event type
508
+ curl -N -H "X-API-Key: your-key" \
509
+ "http://localhost:3000/api/v1/events?event_types=task.created,task.claimed"
510
+ ```
511
+
512
+ ### Reconnection
513
+
514
+ Include `Last-Event-ID` header to resume from where you left off:
515
+
516
+ ```bash
517
+ curl -N -H "X-API-Key: your-key" \
518
+ -H "Last-Event-ID: 42" \
519
+ http://localhost:3000/api/v1/events
520
+ ```
521
+
522
+ ## Multi-Agent Coordination
523
+
524
+ ### Atomic Task Claiming
525
+
526
+ Multiple agents can race to claim the same task. Exactly one wins; the rest receive a 409 Conflict. This uses optimistic locking with a version field and `BEGIN IMMEDIATE` transactions in SQLite.
527
+
528
+ ```bash
529
+ # Claim a task
530
+ curl -X POST http://localhost:3000/api/v1/tasks/42/claim \
531
+ -H "X-API-Key: your-key" \
532
+ -H "Content-Type: application/json" \
533
+ -d '{"assignee": "agent-1"}'
534
+
535
+ # With idempotency key (safe to retry)
536
+ curl -X POST http://localhost:3000/api/v1/tasks/42/claim \
537
+ -H "X-API-Key: your-key" \
538
+ -H "X-Idempotency-Key: unique-key-123" \
539
+ -H "Content-Type: application/json" \
540
+ -d '{"assignee": "agent-1"}'
541
+ ```
542
+
543
+ - Verified with 20 concurrent agents: exactly 1 success, 19 conflicts, 0 errors
544
+ - Stale claims auto-released after 30 minutes of inactivity
545
+ - Idempotency keys prevent duplicate claims (24h TTL)
546
+
547
+ ### Workflow Automation
548
+
549
+ When tasks change status, the system automatically:
550
+
551
+ - **Parent auto-complete:** When all subtasks reach `done`, parent task transitions to `done`
552
+ - **Dependency auto-unblock:** When a blocking task completes, blocked dependents transition from `blocked` to `open`
553
+
554
+ Cascades are depth-limited (max 5 levels) and wrapped in transactions for atomicity.
555
+
556
+ ## Configuration
557
+
558
+ ### Environment Variables
559
+
560
+ | Variable | Description | Default |
561
+ |----------|-------------|---------|
562
+ | PORT | HTTP server port | 3000 |
563
+ | HOST | HTTP server host. Defaults to loopback only; set to `0.0.0.0` (or a specific LAN IP) to expose on the network. | 127.0.0.1 |
564
+ | API_KEYS | Comma-separated legacy API keys (`key` or `key:label`). **Required** — the Zod config schema rejects an empty/unset value (`src/config/env.ts`), so the server exits with code 78 (`EX_CONFIG`) at startup when it is missing. There is no "auth-disabled" mode. | (required — no default) |
565
+ | LOG_LEVEL | Logging level (debug, info, warn, error) | info |
566
+ | NODE_ENV | Environment (development, production) | (none) |
567
+ | DATABASE_PATH | Path to SQLite database file (canonical; MCP server also accepts legacy `DB_PATH`) | ./data/tasks.db |
568
+ | API_BASE_URL | Base URL for CLI API calls | http://localhost:3000 |
569
+ | API_KEY | API key for CLI authentication | (none) |
570
+ | SLACK_BOT_TOKEN / SLACK_APP_TOKEN / SLACK_SIGNING_SECRET | Optional Slack integration (all three required together) — see [docs/SLACK.md](docs/SLACK.md) | (none) |
571
+ | RATE_LIMIT_MAX / RATE_LIMIT_TIME_WINDOW | Global rate limiter knobs | 1000 / "1 minute" |
572
+ | SSE_MAX_CONNECTIONS_PER_KEY / SSE_MAX_CONNECTIONS_PER_IP / SSE_MAX_CONNECTIONS | SSE connection caps | 4 / 8 / 200 |
573
+ | ENABLE_SWAGGER_IN_PRODUCTION | Opt-in to expose Swagger UI when `NODE_ENV=production` | false |
574
+
575
+ [NOTE] The full env-var reference (including server timeouts and installer
576
+ variables) lives in [docs/SETUP.md → Environment Variables](docs/SETUP.md#environment-variables).
577
+
578
+ ## Development
579
+
580
+ ### Key Commands
581
+
582
+ ```bash
583
+ # Development mode with hot reload
584
+ npm run dev
585
+
586
+ # Run tests (2640 tests across 204 files)
587
+ npm test
588
+
589
+ # Watch mode for tests
590
+ npm run test:watch
591
+
592
+ # Build TypeScript
593
+ npm run build
594
+
595
+ # Run CLI in development (without building)
596
+ npm run cli -- <command>
597
+
598
+ # Run MCP server in development
599
+ npm run mcp:dev
600
+ ```
601
+
602
+ ### Database
603
+
604
+ SQLite with better-sqlite3 driver, WAL mode, and automatic migrations via Umzug. Twelve migration files in `src/db/migrations/`:
605
+
606
+ 1. `001-initial-schema.ts` — projects, tasks, task_tags (plus the tasks_fts FTS5 virtual table and sync triggers)
607
+ 2. `002-task-hierarchy-and-dependencies.ts` — adds `parent_task_id` to tasks and creates the `task_dependencies` table
608
+ 3. `003-comments-and-estimates.ts` — creates the `task_comments` table and adds `estimated_minutes` to tasks
609
+ 4. `004-claim-protocol.ts` — version field, claimed_at, idempotency_keys table
610
+ 5. `005-backlogged-status.ts` — adds `backlogged` to the status CHECK constraint (rebuilds tasks table; preserves FTS triggers)
611
+ 6. `006-slack-channel-subscriptions.ts` — `slack_channel_subscriptions` table for the Slack notifier
612
+ 7. `007-completed-at.ts` — `completed_at` column on tasks (set on transition into `done`, backfilled from `updated_at`)
613
+ 8. `008-identity-tables.ts` — `users` and `api_tokens` tables (OIDC/PAT identity)
614
+ 9. `009-parallel-fk-columns.ts` — parallel `*_user_id` FK columns alongside the legacy TEXT identity columns
615
+ 10. `010-identity-uniqueness-indexes.ts` — uniqueness indexes on user identity (oidc_sub, email)
616
+ 11. `011-acceptance-criteria.ts` — `acceptance_criteria` column on tasks
617
+ 12. `012-verification-evidence.ts` — `verification_evidence` column on tasks (verifier verdict + checks)
618
+
619
+ ### Testing
620
+
621
+ 2640 tests across 204 test files covering:
622
+ - Service layer unit tests
623
+ - API route integration tests (all endpoints)
624
+ - MCP tool tests (all tools)
625
+ - CLI command tests
626
+ - Event system tests (EventBus, SSEManager, events API)
627
+ - Claim protocol tests (including 20-agent concurrency)
628
+ - Workflow engine tests (auto-complete, auto-unblock, cascade depth)
629
+ - Skill file validation tests
630
+
631
+ ### Code Quality Roadmap
632
+
633
+ The current TypeScript service quality baseline and the prioritized
634
+ uplift roadmap (lint/format gate, stricter compiler flags, architecture
635
+ guardrails, migration safety, CI/release automation) live in
636
+ [docs/CODE_QUALITY_ROADMAP.md](docs/CODE_QUALITY_ROADMAP.md). It is the
637
+ source of truth for the `Code Quality Uplift Roadmap` project tracked
638
+ in the bugs database and should be linked from future PR/release
639
+ quality checklist work.
640
+
641
+ ## Integrations
642
+
643
+ ### Slack
644
+
645
+ Wood Fired Tasks ships an **optional** Slack integration:
646
+
647
+ - `/tasks` slash command (read, create, update, claim, subscribe channels to notifications, …)
648
+ - A notifier that posts Block Kit messages to subscribed channels when
649
+ task events fire on the internal EventBus.
650
+
651
+ Slack is fully optional — leave `SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN`, and
652
+ `SLACK_SIGNING_SECRET` unset and the service runs without it. The three
653
+ variables are validated as a group (all three, or none).
654
+
655
+ See [docs/SLACK.md](docs/SLACK.md) for: app manifest, required scopes,
656
+ slash-command reference, channel subscription model, error handling.
657
+
658
+ ### Claude Code (MCP)
659
+
660
+ The shipped MCP server registers as a stdio MCP target in `~/.claude.json`
661
+ and exposes 22 tools plus the `/tasks:*` skill files. See
662
+ [docs/MCP.md](docs/MCP.md) and the "Claude Code Integration" section in
663
+ [docs/SETUP.md](docs/SETUP.md#claude-code-integration).
664
+
665
+ The `/tasks:*` skills automate the plan→execute→audit loop. Start with
666
+ **`/tasks:decompose --project <id> --goal "..." --success "..."`** to turn a
667
+ project-level goal into 8–25 well-formed tasks (or a dependency DAG) — it
668
+ advises `/tasks:loop` (FLAT backlog, drained sequentially) or
669
+ `/tasks:loop-dag` (DAG backlog, drained wave-by-wave in parallel), then
670
+ `/tasks:audit` grades the run. Decompose only plans; it never executes the
671
+ tasks it creates, refuses blast-radius goals, and supports `--dry-run` to
672
+ preview the breakdown without touching the database. See
673
+ [skills/tasks/decompose.md](skills/tasks/decompose.md) and its design at
674
+ [docs/tasks-decompose-design.md](docs/tasks-decompose-design.md).
675
+
676
+ ## Release Verification
677
+
678
+ Before publishing to npm, run `npm run pack:check` (alias for
679
+ `npm pack --dry-run`) and inspect the printed file list. Confirm that
680
+ `dist/` JS + `.d.ts` files, `LICENSE`, `README.md`, `CHANGELOG.md`, and
681
+ `SECURITY.md` are present, and that `src/`, `.env*`, `data/*.db`,
682
+ `.planning/`, and test files are **absent**. The package uses an explicit
683
+ `files` allowlist in `package.json` — adjust it there if the output drifts.
684
+
685
+ ## License
686
+
687
+ MIT