@kb-labs/rest-api-app 1.3.0 → 1.4.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 (257) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +8151 -0
  3. package/dist/index.js.map +1 -0
  4. package/package.json +7 -4
  5. package/.kb/agents/sessions/session-1771531145393-ws3uh6q/turns.json +0 -42
  6. package/.kb/agents/sessions/session-1771548930486-ui6rtvm/turns.json +0 -33
  7. package/.kb/agents/sessions/session-1771549691485-nibqroq/turns.json +0 -133
  8. package/.kb/agents/sessions/session-1771550943182-dkwqdjc/turns.json +0 -130
  9. package/.kb/agents/sessions/session-1771551564182-cr4bwzn/turns.json +0 -349
  10. package/.kb/agents/sessions/session-1771552401370-g4ztwd1/turns.json +0 -206
  11. package/.kb/commit/current/plan.json +0 -248
  12. package/.kb/commit/current/status.json +0 -472
  13. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.d.ts +0 -10
  14. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js +0 -215
  15. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/health.js.map +0 -1
  16. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.d.ts +0 -10
  17. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js +0 -271
  18. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/list.js.map +0 -1
  19. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.d.ts +0 -10
  20. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js +0 -230
  21. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/logs.js.map +0 -1
  22. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.d.ts +0 -10
  23. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js +0 -228
  24. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/metrics.js.map +0 -1
  25. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.d.ts +0 -11
  26. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js +0 -281
  27. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/run.js.map +0 -1
  28. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.d.ts +0 -10
  29. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js +0 -266
  30. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/status.js.map +0 -1
  31. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.d.ts +0 -11
  32. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js +0 -284
  33. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/commands/workflow-run.js.map +0 -1
  34. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/flags-WLdpSZl4.d.ts +0 -77
  35. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.d.ts +0 -2
  36. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js +0 -441
  37. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/index.js.map +0 -1
  38. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.d.ts +0 -196
  39. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js +0 -441
  40. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/manifest.js.map +0 -1
  41. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.d.ts +0 -19
  42. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js +0 -48
  43. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/cron-list-handler.js.map +0 -1
  44. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.d.ts +0 -6
  45. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js +0 -170
  46. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/index.js.map +0 -1
  47. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.d.ts +0 -12
  48. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js +0 -52
  49. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-cancel-handler.js.map +0 -1
  50. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.d.ts +0 -22
  51. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js +0 -52
  52. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-detail-handler.js.map +0 -1
  53. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.d.ts +0 -13
  54. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js +0 -52
  55. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-logs-handler.js.map +0 -1
  56. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.d.ts +0 -9
  57. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js +0 -43
  58. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/job-steps-handler.js.map +0 -1
  59. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.d.ts +0 -26
  60. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js +0 -63
  61. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/jobs-list-handler.js.map +0 -1
  62. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.d.ts +0 -9
  63. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js +0 -46
  64. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/pending-approvals-handler.js.map +0 -1
  65. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.d.ts +0 -16
  66. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js +0 -58
  67. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/resolve-approval-handler.js.map +0 -1
  68. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.d.ts +0 -9
  69. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js +0 -46
  70. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/run-detail-handler.js.map +0 -1
  71. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.d.ts +0 -11
  72. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js +0 -50
  73. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/runs-list-handler.js.map +0 -1
  74. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.d.ts +0 -7
  75. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js +0 -39
  76. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/stats-handler.js.map +0 -1
  77. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.d.ts +0 -10
  78. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js +0 -46
  79. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-detail-handler.js.map +0 -1
  80. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.d.ts +0 -13
  81. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js +0 -47
  82. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-cancel-handler.js.map +0 -1
  83. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.d.ts +0 -14
  84. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js +0 -53
  85. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-run-handler.js.map +0 -1
  86. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.d.ts +0 -13
  87. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js +0 -54
  88. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflow-runs-handler.js.map +0 -1
  89. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.d.ts +0 -12
  90. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js +0 -51
  91. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/rest/workflows-list-handler.js.map +0 -1
  92. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.d.ts +0 -17
  93. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js +0 -133
  94. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/logs-channel.js.map +0 -1
  95. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.d.ts +0 -11
  96. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js +0 -46
  97. package/.kb/runtime/workspaces/ws_94c2deab-4cf9-49cb-94ac-3958062754a1/ws/progress-channel.js.map +0 -1
  98. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.d.ts +0 -10
  99. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js +0 -215
  100. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/health.js.map +0 -1
  101. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.d.ts +0 -10
  102. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js +0 -271
  103. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/list.js.map +0 -1
  104. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.d.ts +0 -10
  105. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js +0 -230
  106. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/logs.js.map +0 -1
  107. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.d.ts +0 -10
  108. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js +0 -228
  109. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/metrics.js.map +0 -1
  110. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.d.ts +0 -11
  111. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js +0 -281
  112. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/run.js.map +0 -1
  113. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.d.ts +0 -10
  114. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js +0 -266
  115. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/status.js.map +0 -1
  116. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.d.ts +0 -11
  117. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js +0 -284
  118. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/commands/workflow-run.js.map +0 -1
  119. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/flags-WLdpSZl4.d.ts +0 -77
  120. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.d.ts +0 -2
  121. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js +0 -441
  122. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/index.js.map +0 -1
  123. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.d.ts +0 -196
  124. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js +0 -441
  125. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/manifest.js.map +0 -1
  126. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.d.ts +0 -19
  127. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js +0 -48
  128. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/cron-list-handler.js.map +0 -1
  129. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.d.ts +0 -6
  130. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js +0 -170
  131. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/index.js.map +0 -1
  132. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.d.ts +0 -12
  133. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js +0 -52
  134. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-cancel-handler.js.map +0 -1
  135. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.d.ts +0 -22
  136. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js +0 -52
  137. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-detail-handler.js.map +0 -1
  138. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.d.ts +0 -13
  139. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js +0 -52
  140. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-logs-handler.js.map +0 -1
  141. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.d.ts +0 -9
  142. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js +0 -43
  143. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/job-steps-handler.js.map +0 -1
  144. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.d.ts +0 -26
  145. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js +0 -63
  146. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/jobs-list-handler.js.map +0 -1
  147. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.d.ts +0 -9
  148. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js +0 -46
  149. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/pending-approvals-handler.js.map +0 -1
  150. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.d.ts +0 -16
  151. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js +0 -58
  152. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/resolve-approval-handler.js.map +0 -1
  153. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.d.ts +0 -9
  154. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js +0 -46
  155. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/run-detail-handler.js.map +0 -1
  156. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.d.ts +0 -11
  157. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js +0 -50
  158. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/runs-list-handler.js.map +0 -1
  159. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.d.ts +0 -7
  160. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js +0 -39
  161. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/stats-handler.js.map +0 -1
  162. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.d.ts +0 -10
  163. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js +0 -46
  164. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-detail-handler.js.map +0 -1
  165. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.d.ts +0 -13
  166. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js +0 -47
  167. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-cancel-handler.js.map +0 -1
  168. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.d.ts +0 -14
  169. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js +0 -53
  170. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-run-handler.js.map +0 -1
  171. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.d.ts +0 -13
  172. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js +0 -54
  173. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflow-runs-handler.js.map +0 -1
  174. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.d.ts +0 -12
  175. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js +0 -51
  176. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/rest/workflows-list-handler.js.map +0 -1
  177. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.d.ts +0 -17
  178. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js +0 -133
  179. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/logs-channel.js.map +0 -1
  180. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.d.ts +0 -11
  181. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js +0 -46
  182. package/.kb/runtime/workspaces/ws_f0f301b8-388d-4dc4-b301-475f2bc95f02/ws/progress-channel.js.map +0 -1
  183. package/eslint.config.js +0 -23
  184. package/src/.kb/agents/sessions/session-1773470583796-ximqnfk/kpi-baseline.json +0 -17
  185. package/src/.kb/memory/sessions/session-1773470583796-ximqnfk/fact-sheet.json +0 -1
  186. package/src/bootstrap.ts +0 -233
  187. package/src/diagnostics/header-debug.ts +0 -37
  188. package/src/events/hub.ts +0 -60
  189. package/src/events/index.ts +0 -1
  190. package/src/index.ts +0 -13
  191. package/src/manifest.ts +0 -21
  192. package/src/middleware/__tests__/cache.spec.ts +0 -184
  193. package/src/middleware/__tests__/envelope.spec.ts +0 -268
  194. package/src/middleware/__tests__/metrics.redis.spec.ts +0 -64
  195. package/src/middleware/__tests__/rate-limit.spec.ts +0 -283
  196. package/src/middleware/__tests__/request-id.spec.ts +0 -160
  197. package/src/middleware/cache.ts +0 -67
  198. package/src/middleware/envelope.ts +0 -136
  199. package/src/middleware/error-guard.ts +0 -69
  200. package/src/middleware/index.ts +0 -37
  201. package/src/middleware/metrics.ts +0 -810
  202. package/src/middleware/mock-mode.ts +0 -44
  203. package/src/middleware/prom-metrics.ts +0 -284
  204. package/src/middleware/rate-limit-routes.ts +0 -73
  205. package/src/middleware/rate-limit.ts +0 -72
  206. package/src/middleware/request-id.ts +0 -41
  207. package/src/middleware/request-timeout.ts +0 -69
  208. package/src/middleware/security-headers.ts +0 -24
  209. package/src/middleware/startup-guard.ts +0 -107
  210. package/src/observability/service-contract.ts +0 -192
  211. package/src/plugins/index.ts +0 -118
  212. package/src/routes/__tests__/adapters-date-helpers.spec.ts +0 -332
  213. package/src/routes/__tests__/adapters.spec.ts +0 -680
  214. package/src/routes/__tests__/cache.spec.ts +0 -264
  215. package/src/routes/__tests__/events.spec.ts +0 -434
  216. package/src/routes/__tests__/health.spec.ts +0 -414
  217. package/src/routes/__tests__/logs.spec.ts +0 -494
  218. package/src/routes/__tests__/observability.spec.ts +0 -392
  219. package/src/routes/__tests__/plugins.spec.ts +0 -931
  220. package/src/routes/__tests__/workflow-management.spec.ts +0 -698
  221. package/src/routes/__tests__/workflows.spec.ts +0 -204
  222. package/src/routes/adapter-call.ts +0 -220
  223. package/src/routes/adapters.ts +0 -1206
  224. package/src/routes/analytics.ts +0 -328
  225. package/src/routes/cache.ts +0 -104
  226. package/src/routes/debug-routes.ts +0 -95
  227. package/src/routes/events.ts +0 -115
  228. package/src/routes/health.ts +0 -348
  229. package/src/routes/hello.ts +0 -47
  230. package/src/routes/index.ts +0 -395
  231. package/src/routes/jobs.ts +0 -253
  232. package/src/routes/logs.ts +0 -718
  233. package/src/routes/metrics.ts +0 -120
  234. package/src/routes/observability.ts +0 -1388
  235. package/src/routes/openapi.ts +0 -101
  236. package/src/routes/platform.ts +0 -143
  237. package/src/routes/plugins.ts +0 -998
  238. package/src/routes/readiness.ts +0 -83
  239. package/src/routes/workflow-management.ts +0 -469
  240. package/src/routes/workflows.ts +0 -256
  241. package/src/server.ts +0 -203
  242. package/src/services/historical-metrics.ts +0 -496
  243. package/src/services/incident-analyzer.ts +0 -289
  244. package/src/services/incident-detector.ts +0 -691
  245. package/src/services/incident-schema.sql +0 -76
  246. package/src/services/incident-storage.ts +0 -593
  247. package/src/services/system-metrics-collector.ts +0 -244
  248. package/src/types/fastify.d.ts +0 -58
  249. package/src/utils/__tests__/sse-auth.spec.ts +0 -113
  250. package/src/utils/path-helpers.ts +0 -15
  251. package/src/utils/repo.ts +0 -42
  252. package/src/utils/schema.ts +0 -20
  253. package/src/utils/sse-auth.ts +0 -81
  254. package/test-sandbox.sh +0 -105
  255. package/tsconfig.build.json +0 -15
  256. package/tsconfig.json +0 -9
  257. package/tsup.config.ts +0 -18
@@ -1,810 +0,0 @@
1
- import { performance } from 'node:perf_hooks';
2
- import type { FastifyInstance } from 'fastify';
3
- type RedisStatus = {
4
- enabled: boolean;
5
- healthy: boolean;
6
- roles: { publisher?: string | null; subscriber?: string | null; cache?: string | null };
7
- };
8
- import { OperationMetricsTracker } from '@kb-labs/shared-http';
9
- import {
10
- httpRequestDuration,
11
- httpRequestsTotal,
12
- httpErrorsTotal,
13
- serviceActiveOperations,
14
- serviceOperationDuration,
15
- serviceOperationTotal,
16
- tenantRequestsTotal,
17
- tenantErrorsTotal,
18
- tenantRequestDuration,
19
- } from './prom-metrics';
20
- import { platform } from '@kb-labs/core-runtime';
21
-
22
- /**
23
- * @module @kb-labs/rest-api-app/middleware/metrics
24
- * Metrics collection middleware
25
- */
26
-
27
- /**
28
- * Metrics data
29
- */
30
- type RedisRole = 'publisher' | 'subscriber' | 'cache';
31
-
32
- interface RedisMetrics {
33
- updates: number;
34
- healthyTransitions: number;
35
- unhealthyTransitions: number;
36
- lastUpdateTs: number | null;
37
- lastHealthyTs: number | null;
38
- lastUnhealthyTs: number | null;
39
- lastStatus: {
40
- enabled: boolean;
41
- healthy: boolean;
42
- roles: Record<RedisRole, string | null>;
43
- } | null;
44
- roleStates: Record<RedisRole, Record<string, number>>;
45
- }
46
-
47
- interface Metrics {
48
- requests: {
49
- total: number;
50
- active: number;
51
- byMethod: Record<string, number>;
52
- byStatus: Record<string, number>;
53
- byRoute: Record<string, number>;
54
- byTenant: Record<string, number>; // ← Multi-tenancy support
55
- };
56
- latency: {
57
- total: number;
58
- count: number;
59
- min: number;
60
- max: number;
61
- average: number;
62
- histogram: Map<string, RouteLatencyStats>;
63
- };
64
- errors: {
65
- total: number;
66
- byCode: Record<string, number>;
67
- };
68
- timestamps: {
69
- startTime: number;
70
- lastRequest: number;
71
- };
72
- headers: {
73
- filteredInbound: number;
74
- filteredOutbound: number;
75
- sensitiveInbound: number;
76
- validationErrors: number;
77
- varyApplied: number;
78
- dryRunDecisions: number;
79
- byPlugin: Record<string, HeaderPluginMetrics>;
80
- };
81
- redis: RedisMetrics;
82
- // ← Multi-tenancy support
83
- perTenant: Map<string, {
84
- total: number;
85
- errors: number;
86
- totalLatency: number;
87
- }>;
88
- }
89
-
90
- type RouteLatencyStats = {
91
- count: number;
92
- total: number;
93
- max: number;
94
- byStatus: Record<string, number>;
95
- };
96
-
97
- type HeaderPluginMetrics = {
98
- filteredInbound: number;
99
- filteredOutbound: number;
100
- validationErrors: number;
101
- varyApplied: number;
102
- sensitiveInbound: number;
103
- };
104
-
105
- type HeaderMetricsEntry = {
106
- pluginId?: string;
107
- routeId?: string;
108
- filteredInbound: number;
109
- filteredOutbound: number;
110
- sensitiveInbound: number;
111
- validationErrors: number;
112
- varyApplied: number;
113
- dryRun: boolean;
114
- };
115
-
116
- export type PluginsMetricsSnapshot = {
117
- total: number;
118
- succeeded: number;
119
- failed: number;
120
- elapsedMs: number;
121
- };
122
-
123
- type PluginsMetricsDetails = Record<string, {
124
- routes: number;
125
- status: 'ok' | 'failed';
126
- durationMs: number;
127
- lastError?: string;
128
- }>;
129
-
130
- class PluginsMetricsCollector {
131
- private metrics: PluginsMetricsSnapshot & { details: PluginsMetricsDetails } = this.createDefault();
132
-
133
- private createDefault(): PluginsMetricsSnapshot & { details: PluginsMetricsDetails } {
134
- return {
135
- total: 0,
136
- succeeded: 0,
137
- failed: 0,
138
- elapsedMs: 0,
139
- details: {},
140
- };
141
- }
142
-
143
- reset(): void {
144
- this.metrics = this.createDefault();
145
- }
146
-
147
- recordSuccess(pluginId: string, routes: number, durationMs: number): void {
148
- this.metrics.total += 1;
149
- this.metrics.succeeded += 1;
150
- this.metrics.elapsedMs += durationMs;
151
- this.metrics.details[pluginId] = {
152
- routes,
153
- status: 'ok',
154
- durationMs,
155
- };
156
- }
157
-
158
- recordFailure(pluginId: string, error: string): void {
159
- this.metrics.total += 1;
160
- this.metrics.failed += 1;
161
- this.metrics.details[pluginId] = {
162
- routes: 0,
163
- status: 'failed',
164
- durationMs: 0,
165
- lastError: error,
166
- };
167
- }
168
-
169
- getSnapshot(): PluginsMetricsSnapshot {
170
- return {
171
- total: this.metrics.total,
172
- succeeded: this.metrics.succeeded,
173
- failed: this.metrics.failed,
174
- elapsedMs: Number(this.metrics.elapsedMs.toFixed(2)),
175
- };
176
- }
177
-
178
- getDetails(): PluginsMetricsDetails {
179
- return this.metrics.details;
180
- }
181
- }
182
-
183
- export interface MetricsSnapshot {
184
- requests: Metrics['requests'] & {
185
- success: number;
186
- clientErrors: number;
187
- serverErrors: number;
188
- };
189
- latency: Omit<Metrics['latency'], 'histogram'> & {
190
- histogram: Array<{
191
- route: string;
192
- count: number;
193
- total: number;
194
- max: number;
195
- byStatus: Record<string, number>;
196
- budgetMs: number | null;
197
- pluginId?: string;
198
- }>;
199
- };
200
- perPlugin: Array<{
201
- pluginId?: string;
202
- total: number;
203
- totalDuration: number;
204
- maxDuration: number;
205
- statuses: Record<string, number>;
206
- }>;
207
- perTenant: Array<{
208
- tenantId: string;
209
- total: number;
210
- errors: number;
211
- avgLatencyMs: number;
212
- }>;
213
- errors: Metrics['errors'];
214
- timestamps: Metrics['timestamps'];
215
- headers: {
216
- filteredInbound: number;
217
- filteredOutbound: number;
218
- sensitiveInbound: number;
219
- validationErrors: number;
220
- varyApplied: number;
221
- dryRunDecisions: number;
222
- perPlugin: Array<{
223
- pluginId: string;
224
- filteredInbound: number;
225
- filteredOutbound: number;
226
- validationErrors: number;
227
- varyApplied: number;
228
- sensitiveInbound: number;
229
- }>;
230
- };
231
- redis: {
232
- updates: number;
233
- healthyTransitions: number;
234
- unhealthyTransitions: number;
235
- lastUpdateTs: number | null;
236
- lastHealthyTs: number | null;
237
- lastUnhealthyTs: number | null;
238
- lastStatus: {
239
- enabled: boolean;
240
- healthy: boolean;
241
- roles: Record<RedisRole, string | null>;
242
- } | null;
243
- roleStates: Array<{
244
- role: RedisRole;
245
- states: Array<{ state: string; count: number }>;
246
- }>;
247
- };
248
- }
249
-
250
- class MetricsCollector {
251
- private metrics: Metrics = this.createMetrics();
252
- private pluginsMetrics = new PluginsMetricsCollector();
253
- private lastPluginSnapshot: PluginsMetricsSnapshot | null = null;
254
- private pluginRouteBudgets = new Map<string, { budgetMs: number | null; pluginId?: string }>();
255
-
256
- private createMetrics(): Metrics {
257
- return {
258
- requests: {
259
- total: 0,
260
- active: 0,
261
- byMethod: {},
262
- byStatus: {},
263
- byRoute: {},
264
- byTenant: {}, // ← Multi-tenancy support
265
- },
266
- latency: {
267
- total: 0,
268
- count: 0,
269
- min: Infinity,
270
- max: 0,
271
- average: 0,
272
- histogram: new Map<string, RouteLatencyStats>(),
273
- },
274
- errors: {
275
- total: 0,
276
- byCode: {},
277
- },
278
- timestamps: {
279
- startTime: Date.now(),
280
- lastRequest: Date.now(),
281
- },
282
- headers: {
283
- filteredInbound: 0,
284
- filteredOutbound: 0,
285
- sensitiveInbound: 0,
286
- validationErrors: 0,
287
- varyApplied: 0,
288
- dryRunDecisions: 0,
289
- byPlugin: {},
290
- },
291
- redis: this.createRedisMetrics(),
292
- perTenant: new Map(), // ← Multi-tenancy support
293
- };
294
- }
295
-
296
- private createRedisMetrics(): RedisMetrics {
297
- return {
298
- updates: 0,
299
- healthyTransitions: 0,
300
- unhealthyTransitions: 0,
301
- lastUpdateTs: null,
302
- lastHealthyTs: null,
303
- lastUnhealthyTs: null,
304
- lastStatus: null,
305
- roleStates: {
306
- publisher: {},
307
- subscriber: {},
308
- cache: {},
309
- },
310
- };
311
- }
312
-
313
- recordRequest(method: string, route: string, statusCode: number, durationMs: number, tenantId?: string): void {
314
- this.metrics.requests.total++;
315
- this.metrics.requests.byMethod[method] = (this.metrics.requests.byMethod[method] || 0) + 1;
316
- const statusGroup = `${Math.floor(statusCode / 100)}xx`;
317
- this.metrics.requests.byStatus[statusGroup] = (this.metrics.requests.byStatus[statusGroup] || 0) + 1;
318
-
319
- const normalizedRoute = normalizeRoute(route);
320
- if (normalizedRoute) {
321
- const routeBucket = `${method} ${normalizedRoute}`;
322
- this.metrics.requests.byRoute[routeBucket] = (this.metrics.requests.byRoute[routeBucket] || 0) + 1;
323
- updateLatencyHistogram(this.metrics.latency.histogram, routeBucket, durationMs, statusCode);
324
- }
325
-
326
- // ← Multi-tenancy support: track by tenant
327
- if (tenantId) {
328
- this.metrics.requests.byTenant[tenantId] = (this.metrics.requests.byTenant[tenantId] || 0) + 1;
329
-
330
- const tenantStats = this.metrics.perTenant.get(tenantId) || {
331
- total: 0,
332
- errors: 0,
333
- totalLatency: 0,
334
- };
335
- tenantStats.total++;
336
- tenantStats.totalLatency += durationMs;
337
- if (statusCode >= 400) {
338
- tenantStats.errors++;
339
- }
340
- this.metrics.perTenant.set(tenantId, tenantStats);
341
- }
342
-
343
- this.metrics.latency.count++;
344
- this.metrics.latency.total += durationMs;
345
- this.metrics.latency.min = Math.min(this.metrics.latency.min, durationMs);
346
- this.metrics.latency.max = Math.max(this.metrics.latency.max, durationMs);
347
- this.metrics.latency.average = this.metrics.latency.total / this.metrics.latency.count;
348
- this.metrics.timestamps.lastRequest = Date.now();
349
- }
350
-
351
- incrementActiveRequests(): number {
352
- this.metrics.requests.active += 1;
353
- return this.metrics.requests.active;
354
- }
355
-
356
- decrementActiveRequests(): number {
357
- this.metrics.requests.active = Math.max(0, this.metrics.requests.active - 1);
358
- return this.metrics.requests.active;
359
- }
360
-
361
- getActiveRequests(): number {
362
- return this.metrics.requests.active;
363
- }
364
-
365
- recordError(errorCode: string): void {
366
- this.metrics.errors.total++;
367
- this.metrics.errors.byCode[errorCode] = (this.metrics.errors.byCode[errorCode] || 0) + 1;
368
- }
369
-
370
- recordHeaderMetrics(entry: HeaderMetricsEntry): void {
371
- const headers = this.metrics.headers;
372
- headers.filteredInbound += Math.max(0, entry.filteredInbound);
373
- headers.filteredOutbound += Math.max(0, entry.filteredOutbound);
374
- headers.sensitiveInbound += Math.max(0, entry.sensitiveInbound);
375
- headers.validationErrors += Math.max(0, entry.validationErrors);
376
- headers.varyApplied += Math.max(0, entry.varyApplied);
377
- if (entry.dryRun) {
378
- headers.dryRunDecisions += Math.max(
379
- 0,
380
- entry.filteredInbound + entry.filteredOutbound + entry.validationErrors
381
- );
382
- }
383
-
384
- if (entry.pluginId) {
385
- const existing: HeaderPluginMetrics = headers.byPlugin[entry.pluginId] ?? {
386
- filteredInbound: 0,
387
- filteredOutbound: 0,
388
- validationErrors: 0,
389
- varyApplied: 0,
390
- sensitiveInbound: 0,
391
- };
392
- existing.filteredInbound += Math.max(0, entry.filteredInbound);
393
- existing.filteredOutbound += Math.max(0, entry.filteredOutbound);
394
- existing.validationErrors += Math.max(0, entry.validationErrors);
395
- existing.varyApplied += Math.max(0, entry.varyApplied);
396
- existing.sensitiveInbound += Math.max(0, entry.sensitiveInbound);
397
- headers.byPlugin[entry.pluginId] = existing;
398
- }
399
- }
400
-
401
- recordRedisStatus(status: RedisStatus | null): void {
402
- if (!status) {
403
- return;
404
- }
405
- const now = Date.now();
406
- const redisMetrics = this.metrics.redis;
407
- const previous = redisMetrics.lastStatus;
408
-
409
- redisMetrics.updates += 1;
410
- redisMetrics.lastUpdateTs = now;
411
- if (status.healthy) {
412
- redisMetrics.lastHealthyTs = now;
413
- } else {
414
- redisMetrics.lastUnhealthyTs = now;
415
- }
416
-
417
- if (previous && previous.healthy !== status.healthy) {
418
- if (status.healthy) {
419
- redisMetrics.healthyTransitions += 1;
420
- } else {
421
- redisMetrics.unhealthyTransitions += 1;
422
- }
423
- }
424
-
425
- const normalizedRoles: Record<RedisRole, string | null> = {
426
- publisher: status.roles.publisher ?? null,
427
- subscriber: status.roles.subscriber ?? null,
428
- cache: status.roles.cache ?? null,
429
- };
430
-
431
- (Object.keys(normalizedRoles) as RedisRole[]).forEach((role) => {
432
- const state = normalizedRoles[role] ?? 'unknown';
433
- const bucket = state ?? 'unknown';
434
- redisMetrics.roleStates[role][bucket] =
435
- (redisMetrics.roleStates[role][bucket] ?? 0) + 1;
436
- });
437
-
438
- redisMetrics.lastStatus = {
439
- enabled: status.enabled,
440
- healthy: status.healthy,
441
- roles: normalizedRoles,
442
- };
443
- }
444
-
445
- getMetrics(): MetricsSnapshot {
446
- const avg = this.metrics.latency.count > 0
447
- ? this.metrics.latency.total / this.metrics.latency.count
448
- : 0;
449
-
450
- const perPluginMap = new Map<string, {
451
- pluginId?: string;
452
- total: number;
453
- totalDuration: number;
454
- maxDuration: number;
455
- statuses: Record<string, number>;
456
- }>();
457
-
458
- const histogramArray = Array.from(this.metrics.latency.histogram.entries()).map(([route, stats]) => {
459
- const entry = this.pluginRouteBudgets.get(route);
460
- const pluginId = entry?.pluginId;
461
- if (pluginId) {
462
- let aggregate = perPluginMap.get(pluginId);
463
- if (!aggregate) {
464
- aggregate = {
465
- pluginId,
466
- total: 0,
467
- totalDuration: 0,
468
- maxDuration: 0,
469
- statuses: {},
470
- };
471
- perPluginMap.set(pluginId, aggregate);
472
- }
473
- aggregate.total += stats.count;
474
- aggregate.totalDuration += stats.total;
475
- aggregate.maxDuration = Math.max(aggregate.maxDuration, stats.max);
476
- for (const [statusCode, count] of Object.entries(stats.byStatus)) {
477
- aggregate.statuses[statusCode] = (aggregate.statuses[statusCode] || 0) + count;
478
- }
479
- }
480
-
481
- return {
482
- route,
483
- count: stats.count,
484
- total: stats.total,
485
- max: stats.max,
486
- byStatus: { ...stats.byStatus },
487
- budgetMs: entry?.budgetMs ?? null,
488
- pluginId,
489
- };
490
- });
491
-
492
- const headerPerPlugin = Object.entries(this.metrics.headers.byPlugin).map(([pluginId, data]) => ({
493
- pluginId,
494
- filteredInbound: data.filteredInbound,
495
- filteredOutbound: data.filteredOutbound,
496
- validationErrors: data.validationErrors,
497
- varyApplied: data.varyApplied,
498
- sensitiveInbound: data.sensitiveInbound,
499
- }));
500
-
501
- const redisRoleStates = (Object.keys(this.metrics.redis.roleStates) as RedisRole[]).map((role) => ({
502
- role,
503
- states: Object.entries(this.metrics.redis.roleStates[role]).map(([state, count]) => ({
504
- state,
505
- count,
506
- })),
507
- }));
508
-
509
- const lastRedisStatus = this.metrics.redis.lastStatus
510
- ? {
511
- enabled: this.metrics.redis.lastStatus.enabled,
512
- healthy: this.metrics.redis.lastStatus.healthy,
513
- roles: { ...this.metrics.redis.lastStatus.roles },
514
- }
515
- : null;
516
-
517
- // Serialize perTenant Map to Array
518
- const perTenantArray = Array.from(this.metrics.perTenant.entries()).map(([tenantId, stats]) => ({
519
- tenantId,
520
- total: stats.total,
521
- errors: stats.errors,
522
- avgLatencyMs: stats.total > 0 ? stats.totalLatency / stats.total : 0,
523
- }));
524
-
525
- // Calculate success/error counts from byStatus
526
- const success = (this.metrics.requests.byStatus['2xx'] || 0) + (this.metrics.requests.byStatus['3xx'] || 0);
527
- const clientErrors = this.metrics.requests.byStatus['4xx'] || 0;
528
- const serverErrors = this.metrics.requests.byStatus['5xx'] || 0;
529
-
530
- return {
531
- requests: {
532
- ...this.metrics.requests,
533
- success,
534
- clientErrors,
535
- serverErrors,
536
- },
537
- latency: {
538
- total: this.metrics.latency.total,
539
- count: this.metrics.latency.count,
540
- min: this.metrics.latency.min,
541
- max: this.metrics.latency.max,
542
- average: avg,
543
- histogram: histogramArray,
544
- },
545
- perPlugin: Array.from(perPluginMap.values()),
546
- perTenant: perTenantArray,
547
- errors: { ...this.metrics.errors, byCode: { ...this.metrics.errors.byCode } },
548
- timestamps: { ...this.metrics.timestamps },
549
- headers: {
550
- filteredInbound: this.metrics.headers.filteredInbound,
551
- filteredOutbound: this.metrics.headers.filteredOutbound,
552
- sensitiveInbound: this.metrics.headers.sensitiveInbound,
553
- validationErrors: this.metrics.headers.validationErrors,
554
- varyApplied: this.metrics.headers.varyApplied,
555
- dryRunDecisions: this.metrics.headers.dryRunDecisions,
556
- perPlugin: headerPerPlugin,
557
- },
558
- redis: {
559
- updates: this.metrics.redis.updates,
560
- healthyTransitions: this.metrics.redis.healthyTransitions,
561
- unhealthyTransitions: this.metrics.redis.unhealthyTransitions,
562
- lastUpdateTs: this.metrics.redis.lastUpdateTs,
563
- lastHealthyTs: this.metrics.redis.lastHealthyTs,
564
- lastUnhealthyTs: this.metrics.redis.lastUnhealthyTs,
565
- lastStatus: lastRedisStatus,
566
- roleStates: redisRoleStates,
567
- },
568
- };
569
- }
570
-
571
- reset(): void {
572
- this.metrics = this.createMetrics();
573
- this.pluginsMetrics.reset();
574
- this.lastPluginSnapshot = null;
575
- }
576
-
577
- beginPluginMount(): PluginsMetricsCollector {
578
- this.pluginsMetrics.reset();
579
- return this.pluginsMetrics;
580
- }
581
-
582
- completePluginMount(logger: { info: (...args: any[]) => void; warn: (...args: any[]) => void }): PluginsMetricsSnapshot | null {
583
- const snapshot = this.pluginsMetrics.getSnapshot();
584
- this.lastPluginSnapshot = snapshot;
585
- if (snapshot.total === 0) {
586
- return snapshot;
587
- }
588
-
589
- logger.info('Plugin mount metrics', snapshot);
590
- if (snapshot.failed > 0) {
591
- logger.warn('Plugin mount failures', this.pluginsMetrics.getDetails());
592
- }
593
-
594
- this.pluginsMetrics.reset();
595
- return snapshot;
596
- }
597
-
598
- getLastPluginMountSnapshot(): PluginsMetricsSnapshot | null {
599
- return this.lastPluginSnapshot;
600
- }
601
-
602
- registerRouteBudget(
603
- method: string,
604
- routePath: string,
605
- budgetMs: number | null | undefined,
606
- pluginId?: string
607
- ): void {
608
- const normalized = normalizeRoute(routePath);
609
- if (!normalized) {
610
- return;
611
- }
612
- const bucket = `${method.toUpperCase()} ${normalized}`;
613
- this.pluginRouteBudgets.set(bucket, { budgetMs: budgetMs ?? null, pluginId });
614
- }
615
-
616
- resetPluginRouteBudgets(): void {
617
- this.pluginRouteBudgets.clear();
618
- }
619
-
620
- getRouteBudget(method: string, routePath: string): number | null {
621
- const normalized = normalizeRoute(routePath);
622
- if (!normalized) {
623
- return null;
624
- }
625
- const bucket = `${method.toUpperCase()} ${normalized}`;
626
- const entry = this.pluginRouteBudgets.get(bucket);
627
- return entry ? entry.budgetMs ?? null : null;
628
- }
629
- }
630
-
631
- export const metricsCollector = new MetricsCollector();
632
- export const restDomainOperationMetrics = new OperationMetricsTracker();
633
-
634
- /**
635
- * Sampling strategy for high-frequency endpoints to prevent analytics overload.
636
- *
637
- * - /metrics: 1:100 (Prometheus scraping happens every few seconds)
638
- * - /health, /ready, /observability/health, /observability/describe: 1:10
639
- * - All other endpoints: 1:1 (track everything)
640
- *
641
- * Uses deterministic sampling based on request counter to ensure even distribution.
642
- */
643
- let requestCounter = 0;
644
- function shouldSampleRequest(route: string): boolean {
645
- requestCounter = (requestCounter + 1) % 100;
646
-
647
- // High-frequency metrics endpoints (Prometheus scraping) - sample 1:100
648
- if (route === '/api/v1/metrics') {
649
- return requestCounter === 0; // Only track every 100th request
650
- }
651
-
652
- // Medium-frequency health and observability probes - sample 1:10
653
- if (
654
- route === '/api/v1/health' ||
655
- route === '/api/v1/ready' ||
656
- route === '/api/v1/observability/health' ||
657
- route === '/api/v1/observability/describe'
658
- ) {
659
- return requestCounter % 10 === 0; // Only track every 10th request
660
- }
661
-
662
- // All other endpoints - track every request (1:1)
663
- return true;
664
- }
665
-
666
- export function registerMetricsMiddleware(server: FastifyInstance): void {
667
- server.addHook('onRequest', (request, _reply, done) => {
668
- request.kbMetricsStart = performance.now();
669
- serviceActiveOperations.set(metricsCollector.incrementActiveRequests());
670
- done();
671
- });
672
-
673
- server.addHook('onResponse', (request, reply, done) => {
674
- const start = request.kbMetricsStart ?? performance.now();
675
- const duration = Math.max(performance.now() - start, 0);
676
- const method = (request.method || request.raw.method || 'GET').toUpperCase();
677
- const routePath = request.routeOptions?.url ?? request.url;
678
-
679
- // Extract tenantId from header or env var
680
- const tenantId = (request.headers['x-tenant-id'] as string | undefined) ?? process.env.KB_TENANT_ID ?? 'default';
681
-
682
- // Log request completion with method + full URL + status code + duration
683
- if ((request as any).kbLogger) {
684
- const fullUrl = request.url;
685
- const durationMs = Math.round(duration);
686
- (request as any).kbLogger.info(`✓ ${method} ${fullUrl} ${reply.statusCode} ${durationMs}ms`, {
687
- statusCode: reply.statusCode,
688
- durationMs,
689
- });
690
- }
691
-
692
- // Record to legacy collector
693
- metricsCollector.recordRequest(method, routePath ?? request.url, reply.statusCode, duration, tenantId);
694
- if (reply.statusCode >= 400) {
695
- metricsCollector.recordError(String(reply.statusCode));
696
- }
697
-
698
- // Record to prom-client metrics
699
- const normalizedRoute = normalizeRoute(routePath ?? request.url) ?? 'unknown';
700
- const statusCode = String(reply.statusCode);
701
- const operation = `http.${method} ${normalizedRoute}`;
702
-
703
- // Record request duration histogram (automatically calculates p50/p95/p99)
704
- httpRequestDuration.observe(
705
- {
706
- method,
707
- route: normalizedRoute,
708
- status_code: statusCode,
709
- tenant: tenantId,
710
- plugin: '', // Will be populated from route metadata if available
711
- },
712
- duration
713
- );
714
-
715
- // Record request counter
716
- httpRequestsTotal.inc({
717
- method,
718
- route: normalizedRoute,
719
- status_code: statusCode,
720
- tenant: tenantId,
721
- plugin: '',
722
- });
723
-
724
- // Record errors
725
- if (reply.statusCode >= 400) {
726
- httpErrorsTotal.inc({
727
- status_code: statusCode,
728
- error_code: String((reply as any).errorCode ?? reply.statusCode),
729
- tenant: tenantId,
730
- });
731
- tenantErrorsTotal.inc({ tenant: tenantId });
732
- }
733
-
734
- serviceOperationTotal.inc({
735
- operation,
736
- status: reply.statusCode >= 400 ? 'error' : 'ok',
737
- });
738
- serviceOperationDuration.observe(
739
- {
740
- operation,
741
- status: reply.statusCode >= 400 ? 'error' : 'ok',
742
- },
743
- duration,
744
- );
745
-
746
- // Record tenant metrics
747
- tenantRequestsTotal.inc({ tenant: tenantId });
748
- tenantRequestDuration.observe({ tenant: tenantId }, duration);
749
-
750
- // Track to analytics for long-term storage (async, fire-and-forget)
751
- // This enables quarterly/annual reports and endpoint usage analysis
752
- // Skip OPTIONS (CORS preflight) - they don't carry useful information
753
- if (method !== 'OPTIONS') {
754
- const { analytics } = platform;
755
- if (analytics) {
756
- // Sample high-frequency probe endpoints (1:100 for metrics, 1:10 for health/ready/observability)
757
- // This prevents overwhelming analytics with 142k+ ping-pong events
758
- const shouldSample = shouldSampleRequest(normalizedRoute);
759
-
760
- if (shouldSample) {
761
- analytics.track('api.request', {
762
- endpoint: normalizedRoute,
763
- method,
764
- statusCode: reply.statusCode,
765
- durationMs: Math.round(duration),
766
- tenantId,
767
- pluginId: (request as any).kbPluginId ?? undefined,
768
- clientVersion: request.headers['x-client-version'] as string | undefined,
769
- userAgent: request.headers['user-agent'] as string | undefined,
770
- requestId: request.id as string | undefined,
771
- }).catch(() => {
772
- // Silently ignore analytics errors - should not affect request handling
773
- });
774
- }
775
- }
776
- }
777
-
778
- serviceActiveOperations.set(metricsCollector.decrementActiveRequests());
779
- done();
780
- });
781
- }
782
-
783
- function normalizeRoute(route: string): string | null {
784
- if (!route) {
785
- return null;
786
- }
787
- const routePath = route.split('?')[0];
788
- if (!routePath) {
789
- return null;
790
- }
791
- return routePath.replace(/\/[0-9a-fA-F-]{6,}/g, '/:id');
792
- }
793
-
794
- function updateLatencyHistogram(
795
- histogram: Map<string, RouteLatencyStats>,
796
- bucket: string,
797
- durationMs: number,
798
- statusCode: number
799
- ): void {
800
- let stats = histogram.get(bucket);
801
- if (!stats) {
802
- stats = { count: 0, total: 0, max: 0, byStatus: {} };
803
- histogram.set(bucket, stats);
804
- }
805
- stats.count += 1;
806
- stats.total += durationMs;
807
- stats.max = Math.max(stats.max, durationMs);
808
- const statusKey = `${statusCode}`;
809
- stats.byStatus[statusKey] = (stats.byStatus[statusKey] || 0) + 1;
810
- }