@oscharko-dev/keiko-server 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/assistant-response.d.ts +6 -0
  3. package/dist/assistant-response.d.ts.map +1 -0
  4. package/dist/assistant-response.js +12 -0
  5. package/dist/browser.d.ts +11 -0
  6. package/dist/browser.d.ts.map +1 -0
  7. package/dist/browser.js +245 -0
  8. package/dist/chat-handlers.d.ts +48 -0
  9. package/dist/chat-handlers.d.ts.map +1 -0
  10. package/dist/chat-handlers.js +821 -0
  11. package/dist/chat-stream-handlers.d.ts +4 -0
  12. package/dist/chat-stream-handlers.d.ts.map +1 -0
  13. package/dist/chat-stream-handlers.js +136 -0
  14. package/dist/conversation-prompt.d.ts +8 -0
  15. package/dist/conversation-prompt.d.ts.map +1 -0
  16. package/dist/conversation-prompt.js +36 -0
  17. package/dist/conversation-validation.d.ts +26 -0
  18. package/dist/conversation-validation.d.ts.map +1 -0
  19. package/dist/conversation-validation.js +125 -0
  20. package/dist/credentialPersistence.d.ts +23 -0
  21. package/dist/credentialPersistence.d.ts.map +1 -0
  22. package/dist/credentialPersistence.js +93 -0
  23. package/dist/credentialVault.d.ts +30 -0
  24. package/dist/credentialVault.d.ts.map +1 -0
  25. package/dist/credentialVault.js +206 -0
  26. package/dist/csp.d.ts +3 -0
  27. package/dist/csp.d.ts.map +1 -0
  28. package/dist/csp.js +75 -0
  29. package/dist/deps.d.ts +78 -0
  30. package/dist/deps.d.ts.map +1 -0
  31. package/dist/deps.js +457 -0
  32. package/dist/editor/agentRoutes.d.ts +7 -0
  33. package/dist/editor/agentRoutes.d.ts.map +1 -0
  34. package/dist/editor/agentRoutes.js +197 -0
  35. package/dist/editor/assuredGateRunner.d.ts +36 -0
  36. package/dist/editor/assuredGateRunner.d.ts.map +1 -0
  37. package/dist/editor/assuredGateRunner.js +100 -0
  38. package/dist/editor/assuredPreFilter.d.ts +34 -0
  39. package/dist/editor/assuredPreFilter.d.ts.map +1 -0
  40. package/dist/editor/assuredPreFilter.js +134 -0
  41. package/dist/editor/assuredPreFilterRunner.d.ts +31 -0
  42. package/dist/editor/assuredPreFilterRunner.d.ts.map +1 -0
  43. package/dist/editor/assuredPreFilterRunner.js +312 -0
  44. package/dist/editor/builtinLanguageProviders.d.ts +6 -0
  45. package/dist/editor/builtinLanguageProviders.d.ts.map +1 -0
  46. package/dist/editor/builtinLanguageProviders.js +221 -0
  47. package/dist/editor/codingContext.d.ts +12 -0
  48. package/dist/editor/codingContext.d.ts.map +1 -0
  49. package/dist/editor/codingContext.js +121 -0
  50. package/dist/editor/codingContextEvidence.d.ts +7 -0
  51. package/dist/editor/codingContextEvidence.d.ts.map +1 -0
  52. package/dist/editor/codingContextEvidence.js +52 -0
  53. package/dist/editor/codingContextProviders.d.ts +36 -0
  54. package/dist/editor/codingContextProviders.d.ts.map +1 -0
  55. package/dist/editor/codingContextProviders.js +348 -0
  56. package/dist/editor/completionModelEvidence.d.ts +16 -0
  57. package/dist/editor/completionModelEvidence.d.ts.map +1 -0
  58. package/dist/editor/completionModelEvidence.js +50 -0
  59. package/dist/editor/completionRoutes.d.ts +37 -0
  60. package/dist/editor/completionRoutes.d.ts.map +1 -0
  61. package/dist/editor/completionRoutes.js +411 -0
  62. package/dist/editor/contextRoutes.d.ts +6 -0
  63. package/dist/editor/contextRoutes.d.ts.map +1 -0
  64. package/dist/editor/contextRoutes.js +411 -0
  65. package/dist/editor/disposableAssuredExecution.d.ts +22 -0
  66. package/dist/editor/disposableAssuredExecution.d.ts.map +1 -0
  67. package/dist/editor/disposableAssuredExecution.js +57 -0
  68. package/dist/editor/editorCompletionModel.d.ts +47 -0
  69. package/dist/editor/editorCompletionModel.d.ts.map +1 -0
  70. package/dist/editor/editorCompletionModel.js +156 -0
  71. package/dist/editor/editorInlineCompletionModel.d.ts +34 -0
  72. package/dist/editor/editorInlineCompletionModel.d.ts.map +1 -0
  73. package/dist/editor/editorInlineCompletionModel.js +112 -0
  74. package/dist/editor/editorModelTokenBudget.d.ts +46 -0
  75. package/dist/editor/editorModelTokenBudget.d.ts.map +1 -0
  76. package/dist/editor/editorModelTokenBudget.js +121 -0
  77. package/dist/editor/inlineCompletionRateLimiter.d.ts +19 -0
  78. package/dist/editor/inlineCompletionRateLimiter.d.ts.map +1 -0
  79. package/dist/editor/inlineCompletionRateLimiter.js +46 -0
  80. package/dist/editor/inlineCompletionRoutes.d.ts +26 -0
  81. package/dist/editor/inlineCompletionRoutes.d.ts.map +1 -0
  82. package/dist/editor/inlineCompletionRoutes.js +404 -0
  83. package/dist/editor/inlineCompletionTelemetryEvidence.d.ts +5 -0
  84. package/dist/editor/inlineCompletionTelemetryEvidence.d.ts.map +1 -0
  85. package/dist/editor/inlineCompletionTelemetryEvidence.js +42 -0
  86. package/dist/editor/languageCancellation.d.ts +19 -0
  87. package/dist/editor/languageCancellation.d.ts.map +1 -0
  88. package/dist/editor/languageCancellation.js +48 -0
  89. package/dist/editor/languageProvider.d.ts +39 -0
  90. package/dist/editor/languageProvider.d.ts.map +1 -0
  91. package/dist/editor/languageProvider.js +11 -0
  92. package/dist/editor/languageRoutes.d.ts +15 -0
  93. package/dist/editor/languageRoutes.d.ts.map +1 -0
  94. package/dist/editor/languageRoutes.js +106 -0
  95. package/dist/editor/languageSanitize.d.ts +8 -0
  96. package/dist/editor/languageSanitize.d.ts.map +1 -0
  97. package/dist/editor/languageSanitize.js +101 -0
  98. package/dist/editor/languageService.d.ts +36 -0
  99. package/dist/editor/languageService.d.ts.map +1 -0
  100. package/dist/editor/languageService.js +93 -0
  101. package/dist/editor/languageServiceHost.d.ts +14 -0
  102. package/dist/editor/languageServiceHost.d.ts.map +1 -0
  103. package/dist/editor/languageServiceHost.js +242 -0
  104. package/dist/editor/localKnowledgeRetrieval.d.ts +21 -0
  105. package/dist/editor/localKnowledgeRetrieval.d.ts.map +1 -0
  106. package/dist/editor/localKnowledgeRetrieval.js +44 -0
  107. package/dist/editor/patchApplyEvidence.d.ts +21 -0
  108. package/dist/editor/patchApplyEvidence.d.ts.map +1 -0
  109. package/dist/editor/patchApplyEvidence.js +87 -0
  110. package/dist/editor/patchApplyRoutes.d.ts +16 -0
  111. package/dist/editor/patchApplyRoutes.d.ts.map +1 -0
  112. package/dist/editor/patchApplyRoutes.js +307 -0
  113. package/dist/editor/postApplyVerification.d.ts +42 -0
  114. package/dist/editor/postApplyVerification.d.ts.map +1 -0
  115. package/dist/editor/postApplyVerification.js +177 -0
  116. package/dist/editor/testGenerationEvidence.d.ts +6 -0
  117. package/dist/editor/testGenerationEvidence.d.ts.map +1 -0
  118. package/dist/editor/testGenerationEvidence.js +72 -0
  119. package/dist/editor/testGenerationPatch.d.ts +10 -0
  120. package/dist/editor/testGenerationPatch.d.ts.map +1 -0
  121. package/dist/editor/testGenerationPatch.js +66 -0
  122. package/dist/editor/testGenerationRoutes.d.ts +21 -0
  123. package/dist/editor/testGenerationRoutes.d.ts.map +1 -0
  124. package/dist/editor/testGenerationRoutes.js +254 -0
  125. package/dist/editor/testGenerationRunner.d.ts +23 -0
  126. package/dist/editor/testGenerationRunner.d.ts.map +1 -0
  127. package/dist/editor/testGenerationRunner.js +120 -0
  128. package/dist/editor/textOffsets.d.ts +6 -0
  129. package/dist/editor/textOffsets.d.ts.map +1 -0
  130. package/dist/editor/textOffsets.js +82 -0
  131. package/dist/editor/typescriptLanguageProvider.d.ts +3 -0
  132. package/dist/editor/typescriptLanguageProvider.d.ts.map +1 -0
  133. package/dist/editor/typescriptLanguageProvider.js +217 -0
  134. package/dist/evidence.d.ts +28 -0
  135. package/dist/evidence.d.ts.map +1 -0
  136. package/dist/evidence.js +145 -0
  137. package/dist/files-deny.d.ts +3 -0
  138. package/dist/files-deny.d.ts.map +1 -0
  139. package/dist/files-deny.js +12 -0
  140. package/dist/files.d.ts +97 -0
  141. package/dist/files.d.ts.map +1 -0
  142. package/dist/files.js +733 -0
  143. package/dist/gateway-setup.d.ts +10 -0
  144. package/dist/gateway-setup.d.ts.map +1 -0
  145. package/dist/gateway-setup.js +896 -0
  146. package/dist/governed-workflow.d.ts +17 -0
  147. package/dist/governed-workflow.d.ts.map +1 -0
  148. package/dist/governed-workflow.js +147 -0
  149. package/dist/grounded-answer.d.ts +12 -0
  150. package/dist/grounded-answer.d.ts.map +1 -0
  151. package/dist/grounded-answer.js +69 -0
  152. package/dist/grounded-context-index.d.ts +25 -0
  153. package/dist/grounded-context-index.d.ts.map +1 -0
  154. package/dist/grounded-context-index.js +169 -0
  155. package/dist/grounded-document-evidence.d.ts +28 -0
  156. package/dist/grounded-document-evidence.d.ts.map +1 -0
  157. package/dist/grounded-document-evidence.js +430 -0
  158. package/dist/grounded-handoff.d.ts +4 -0
  159. package/dist/grounded-handoff.d.ts.map +1 -0
  160. package/dist/grounded-handoff.js +445 -0
  161. package/dist/grounded-orchestrator.d.ts +43 -0
  162. package/dist/grounded-orchestrator.d.ts.map +1 -0
  163. package/dist/grounded-orchestrator.js +1445 -0
  164. package/dist/grounded-prompt.d.ts +2 -0
  165. package/dist/grounded-prompt.d.ts.map +1 -0
  166. package/dist/grounded-prompt.js +17 -0
  167. package/dist/grounded-qa-hybrid.d.ts +36 -0
  168. package/dist/grounded-qa-hybrid.d.ts.map +1 -0
  169. package/dist/grounded-qa-hybrid.js +762 -0
  170. package/dist/grounded-qa-multi-source.d.ts +38 -0
  171. package/dist/grounded-qa-multi-source.d.ts.map +1 -0
  172. package/dist/grounded-qa-multi-source.js +461 -0
  173. package/dist/grounded-qa.d.ts +45 -0
  174. package/dist/grounded-qa.d.ts.map +1 -0
  175. package/dist/grounded-qa.js +877 -0
  176. package/dist/grounded-rerank.d.ts +26 -0
  177. package/dist/grounded-rerank.d.ts.map +1 -0
  178. package/dist/grounded-rerank.js +72 -0
  179. package/dist/grounded-turn-registry.d.ts +23 -0
  180. package/dist/grounded-turn-registry.d.ts.map +1 -0
  181. package/dist/grounded-turn-registry.js +102 -0
  182. package/dist/headers.d.ts +3 -0
  183. package/dist/headers.d.ts.map +1 -0
  184. package/dist/headers.js +22 -0
  185. package/dist/host-check.d.ts +3 -0
  186. package/dist/host-check.d.ts.map +1 -0
  187. package/dist/host-check.js +58 -0
  188. package/dist/index.d.ts +26 -0
  189. package/dist/index.d.ts.map +1 -0
  190. package/dist/index.js +33 -0
  191. package/dist/load-csp.d.ts +3 -0
  192. package/dist/load-csp.d.ts.map +1 -0
  193. package/dist/load-csp.js +100 -0
  194. package/dist/local-knowledge-grounded-qa.d.ts +42 -0
  195. package/dist/local-knowledge-grounded-qa.d.ts.map +1 -0
  196. package/dist/local-knowledge-grounded-qa.js +678 -0
  197. package/dist/local-knowledge-handlers.d.ts +24 -0
  198. package/dist/local-knowledge-handlers.d.ts.map +1 -0
  199. package/dist/local-knowledge-handlers.js +1285 -0
  200. package/dist/local-knowledge-indexing-registry.d.ts +13 -0
  201. package/dist/local-knowledge-indexing-registry.d.ts.map +1 -0
  202. package/dist/local-knowledge-indexing-registry.js +53 -0
  203. package/dist/localKnowledgeKeyProvider.d.ts +11 -0
  204. package/dist/localKnowledgeKeyProvider.d.ts.map +1 -0
  205. package/dist/localKnowledgeKeyProvider.js +48 -0
  206. package/dist/memory-audit-event-builders.d.ts +21 -0
  207. package/dist/memory-audit-event-builders.d.ts.map +1 -0
  208. package/dist/memory-audit-event-builders.js +187 -0
  209. package/dist/memory-audit-handler.d.ts +23 -0
  210. package/dist/memory-audit-handler.d.ts.map +1 -0
  211. package/dist/memory-audit-handler.js +191 -0
  212. package/dist/memory-capture-policy.d.ts +10 -0
  213. package/dist/memory-capture-policy.d.ts.map +1 -0
  214. package/dist/memory-capture-policy.js +44 -0
  215. package/dist/memory-consolidation-handlers.d.ts +6 -0
  216. package/dist/memory-consolidation-handlers.d.ts.map +1 -0
  217. package/dist/memory-consolidation-handlers.js +491 -0
  218. package/dist/memory-consolidation-registry.d.ts +47 -0
  219. package/dist/memory-consolidation-registry.d.ts.map +1 -0
  220. package/dist/memory-consolidation-registry.js +106 -0
  221. package/dist/memory-conv-handlers.d.ts +8 -0
  222. package/dist/memory-conv-handlers.d.ts.map +1 -0
  223. package/dist/memory-conv-handlers.js +369 -0
  224. package/dist/memory-conversation-context.d.ts +13 -0
  225. package/dist/memory-conversation-context.d.ts.map +1 -0
  226. package/dist/memory-conversation-context.js +22 -0
  227. package/dist/memory-diagnostics.d.ts +29 -0
  228. package/dist/memory-diagnostics.d.ts.map +1 -0
  229. package/dist/memory-diagnostics.js +122 -0
  230. package/dist/memory-embedding.d.ts +21 -0
  231. package/dist/memory-embedding.d.ts.map +1 -0
  232. package/dist/memory-embedding.js +264 -0
  233. package/dist/memory-handlers.d.ts +19 -0
  234. package/dist/memory-handlers.d.ts.map +1 -0
  235. package/dist/memory-handlers.js +1204 -0
  236. package/dist/memory-maintenance-handlers.d.ts +35 -0
  237. package/dist/memory-maintenance-handlers.d.ts.map +1 -0
  238. package/dist/memory-maintenance-handlers.js +219 -0
  239. package/dist/memory-record-builders.d.ts +4 -0
  240. package/dist/memory-record-builders.d.ts.map +1 -0
  241. package/dist/memory-record-builders.js +19 -0
  242. package/dist/memory-retention.d.ts +31 -0
  243. package/dist/memory-retention.d.ts.map +1 -0
  244. package/dist/memory-retention.js +151 -0
  245. package/dist/memory-retrieval-signals.d.ts +12 -0
  246. package/dist/memory-retrieval-signals.d.ts.map +1 -0
  247. package/dist/memory-retrieval-signals.js +100 -0
  248. package/dist/memory-salience.d.ts +12 -0
  249. package/dist/memory-salience.d.ts.map +1 -0
  250. package/dist/memory-salience.js +154 -0
  251. package/dist/memory-scope-sanitizer.d.ts +6 -0
  252. package/dist/memory-scope-sanitizer.d.ts.map +1 -0
  253. package/dist/memory-scope-sanitizer.js +106 -0
  254. package/dist/memory-target-resolver.d.ts +4 -0
  255. package/dist/memory-target-resolver.d.ts.map +1 -0
  256. package/dist/memory-target-resolver.js +73 -0
  257. package/dist/memory-workflow-port.d.ts +14 -0
  258. package/dist/memory-workflow-port.d.ts.map +1 -0
  259. package/dist/memory-workflow-port.js +186 -0
  260. package/dist/private-json.d.ts +3 -0
  261. package/dist/private-json.d.ts.map +1 -0
  262. package/dist/private-json.js +62 -0
  263. package/dist/promptEnhancer/index.d.ts +3 -0
  264. package/dist/promptEnhancer/index.d.ts.map +1 -0
  265. package/dist/promptEnhancer/index.js +5 -0
  266. package/dist/promptEnhancer/orchestrate.d.ts +2 -0
  267. package/dist/promptEnhancer/orchestrate.d.ts.map +1 -0
  268. package/dist/promptEnhancer/orchestrate.js +5 -0
  269. package/dist/promptEnhancer/routes.d.ts +9 -0
  270. package/dist/promptEnhancer/routes.d.ts.map +1 -0
  271. package/dist/promptEnhancer/routes.js +205 -0
  272. package/dist/qualityIntelligence/capsuleAdapter.d.ts +27 -0
  273. package/dist/qualityIntelligence/capsuleAdapter.d.ts.map +1 -0
  274. package/dist/qualityIntelligence/capsuleAdapter.js +57 -0
  275. package/dist/qualityIntelligence/connectorAuthorization.d.ts +22 -0
  276. package/dist/qualityIntelligence/connectorAuthorization.d.ts.map +1 -0
  277. package/dist/qualityIntelligence/connectorAuthorization.js +35 -0
  278. package/dist/qualityIntelligence/connectorErrors.d.ts +16 -0
  279. package/dist/qualityIntelligence/connectorErrors.d.ts.map +1 -0
  280. package/dist/qualityIntelligence/connectorErrors.js +56 -0
  281. package/dist/qualityIntelligence/connectorRoutes.d.ts +7 -0
  282. package/dist/qualityIntelligence/connectorRoutes.d.ts.map +1 -0
  283. package/dist/qualityIntelligence/connectorRoutes.js +167 -0
  284. package/dist/qualityIntelligence/editRoutes.d.ts +5 -0
  285. package/dist/qualityIntelligence/editRoutes.d.ts.map +1 -0
  286. package/dist/qualityIntelligence/editRoutes.js +293 -0
  287. package/dist/qualityIntelligence/exportAssembly.d.ts +22 -0
  288. package/dist/qualityIntelligence/exportAssembly.d.ts.map +1 -0
  289. package/dist/qualityIntelligence/exportAssembly.js +352 -0
  290. package/dist/qualityIntelligence/exportRoutes.d.ts +5 -0
  291. package/dist/qualityIntelligence/exportRoutes.d.ts.map +1 -0
  292. package/dist/qualityIntelligence/exportRoutes.js +320 -0
  293. package/dist/qualityIntelligence/figma/figmaConcurrency.d.ts +8 -0
  294. package/dist/qualityIntelligence/figma/figmaConcurrency.d.ts.map +1 -0
  295. package/dist/qualityIntelligence/figma/figmaConcurrency.js +34 -0
  296. package/dist/qualityIntelligence/figma/figmaConnector.d.ts +65 -0
  297. package/dist/qualityIntelligence/figma/figmaConnector.d.ts.map +1 -0
  298. package/dist/qualityIntelligence/figma/figmaConnector.js +184 -0
  299. package/dist/qualityIntelligence/figma/figmaConnectorAudit.d.ts +52 -0
  300. package/dist/qualityIntelligence/figma/figmaConnectorAudit.d.ts.map +1 -0
  301. package/dist/qualityIntelligence/figma/figmaConnectorAudit.js +63 -0
  302. package/dist/qualityIntelligence/figma/figmaConnectorErrors.d.ts +31 -0
  303. package/dist/qualityIntelligence/figma/figmaConnectorErrors.d.ts.map +1 -0
  304. package/dist/qualityIntelligence/figma/figmaConnectorErrors.js +220 -0
  305. package/dist/qualityIntelligence/figma/figmaConnectorMetrics.d.ts +44 -0
  306. package/dist/qualityIntelligence/figma/figmaConnectorMetrics.d.ts.map +1 -0
  307. package/dist/qualityIntelligence/figma/figmaConnectorMetrics.js +49 -0
  308. package/dist/qualityIntelligence/figma/figmaConsent.d.ts +39 -0
  309. package/dist/qualityIntelligence/figma/figmaConsent.d.ts.map +1 -0
  310. package/dist/qualityIntelligence/figma/figmaConsent.js +62 -0
  311. package/dist/qualityIntelligence/figma/figmaHttpPort.d.ts +28 -0
  312. package/dist/qualityIntelligence/figma/figmaHttpPort.d.ts.map +1 -0
  313. package/dist/qualityIntelligence/figma/figmaHttpPort.js +70 -0
  314. package/dist/qualityIntelligence/figma/figmaObservedActions.d.ts +49 -0
  315. package/dist/qualityIntelligence/figma/figmaObservedActions.d.ts.map +1 -0
  316. package/dist/qualityIntelligence/figma/figmaObservedActions.js +89 -0
  317. package/dist/qualityIntelligence/figma/figmaReadiness.d.ts +32 -0
  318. package/dist/qualityIntelligence/figma/figmaReadiness.d.ts.map +1 -0
  319. package/dist/qualityIntelligence/figma/figmaReadiness.js +67 -0
  320. package/dist/qualityIntelligence/figma/figmaRenderPort.d.ts +29 -0
  321. package/dist/qualityIntelligence/figma/figmaRenderPort.d.ts.map +1 -0
  322. package/dist/qualityIntelligence/figma/figmaRenderPort.js +93 -0
  323. package/dist/qualityIntelligence/figma/figmaResnapshot.d.ts +28 -0
  324. package/dist/qualityIntelligence/figma/figmaResnapshot.d.ts.map +1 -0
  325. package/dist/qualityIntelligence/figma/figmaResnapshot.js +38 -0
  326. package/dist/qualityIntelligence/figma/figmaRetry.d.ts +31 -0
  327. package/dist/qualityIntelligence/figma/figmaRetry.d.ts.map +1 -0
  328. package/dist/qualityIntelligence/figma/figmaRetry.js +62 -0
  329. package/dist/qualityIntelligence/figma/figmaScopeRef.d.ts +9 -0
  330. package/dist/qualityIntelligence/figma/figmaScopeRef.d.ts.map +1 -0
  331. package/dist/qualityIntelligence/figma/figmaScopeRef.js +18 -0
  332. package/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts +86 -0
  333. package/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts.map +1 -0
  334. package/dist/qualityIntelligence/figma/figmaScopedPagination.js +308 -0
  335. package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts +31 -0
  336. package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts.map +1 -0
  337. package/dist/qualityIntelligence/figma/figmaSnapshotBuilder.js +314 -0
  338. package/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts +18 -0
  339. package/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts.map +1 -0
  340. package/dist/qualityIntelligence/figma/figmaSnapshotHash.js +63 -0
  341. package/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts +65 -0
  342. package/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts.map +1 -0
  343. package/dist/qualityIntelligence/figma/figmaSnapshotTypes.js +13 -0
  344. package/dist/qualityIntelligence/figma/figmaTokenSource.d.ts +9 -0
  345. package/dist/qualityIntelligence/figma/figmaTokenSource.d.ts.map +1 -0
  346. package/dist/qualityIntelligence/figma/figmaTokenSource.js +61 -0
  347. package/dist/qualityIntelligence/figma/figmaTokenStore.d.ts +19 -0
  348. package/dist/qualityIntelligence/figma/figmaTokenStore.d.ts.map +1 -0
  349. package/dist/qualityIntelligence/figma/figmaTokenStore.js +156 -0
  350. package/dist/qualityIntelligence/figma/figmaUrl.d.ts +6 -0
  351. package/dist/qualityIntelligence/figma/figmaUrl.d.ts.map +1 -0
  352. package/dist/qualityIntelligence/figma/figmaUrl.js +36 -0
  353. package/dist/qualityIntelligence/figma/index.d.ts +20 -0
  354. package/dist/qualityIntelligence/figma/index.d.ts.map +1 -0
  355. package/dist/qualityIntelligence/figma/index.js +26 -0
  356. package/dist/qualityIntelligence/figmaCodegenRoutes.d.ts +28 -0
  357. package/dist/qualityIntelligence/figmaCodegenRoutes.d.ts.map +1 -0
  358. package/dist/qualityIntelligence/figmaCodegenRoutes.js +165 -0
  359. package/dist/qualityIntelligence/figmaSnapshotAdapter.d.ts +55 -0
  360. package/dist/qualityIntelligence/figmaSnapshotAdapter.d.ts.map +1 -0
  361. package/dist/qualityIntelligence/figmaSnapshotAdapter.js +219 -0
  362. package/dist/qualityIntelligence/figmaSnapshotOrchestration.d.ts +64 -0
  363. package/dist/qualityIntelligence/figmaSnapshotOrchestration.d.ts.map +1 -0
  364. package/dist/qualityIntelligence/figmaSnapshotOrchestration.js +203 -0
  365. package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +112 -0
  366. package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -0
  367. package/dist/qualityIntelligence/figmaSnapshotRoutes.js +1063 -0
  368. package/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts +19 -0
  369. package/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts.map +1 -0
  370. package/dist/qualityIntelligence/figmaSnapshotScreenIds.js +75 -0
  371. package/dist/qualityIntelligence/generationPort.d.ts +15 -0
  372. package/dist/qualityIntelligence/generationPort.d.ts.map +1 -0
  373. package/dist/qualityIntelligence/generationPort.js +185 -0
  374. package/dist/qualityIntelligence/handoffErrors.d.ts +9 -0
  375. package/dist/qualityIntelligence/handoffErrors.d.ts.map +1 -0
  376. package/dist/qualityIntelligence/handoffErrors.js +21 -0
  377. package/dist/qualityIntelligence/handoffRoutes.d.ts +15 -0
  378. package/dist/qualityIntelligence/handoffRoutes.d.ts.map +1 -0
  379. package/dist/qualityIntelligence/handoffRoutes.js +341 -0
  380. package/dist/qualityIntelligence/index.d.ts +17 -0
  381. package/dist/qualityIntelligence/index.d.ts.map +1 -0
  382. package/dist/qualityIntelligence/index.js +36 -0
  383. package/dist/qualityIntelligence/judgePort.d.ts +30 -0
  384. package/dist/qualityIntelligence/judgePort.d.ts.map +1 -0
  385. package/dist/qualityIntelligence/judgePort.js +326 -0
  386. package/dist/qualityIntelligence/modelSelection.d.ts +58 -0
  387. package/dist/qualityIntelligence/modelSelection.d.ts.map +1 -0
  388. package/dist/qualityIntelligence/modelSelection.js +148 -0
  389. package/dist/qualityIntelligence/reCheckRoutes.d.ts +6 -0
  390. package/dist/qualityIntelligence/reCheckRoutes.d.ts.map +1 -0
  391. package/dist/qualityIntelligence/reCheckRoutes.js +1157 -0
  392. package/dist/qualityIntelligence/retentionEnforcement.d.ts +13 -0
  393. package/dist/qualityIntelligence/retentionEnforcement.d.ts.map +1 -0
  394. package/dist/qualityIntelligence/retentionEnforcement.js +47 -0
  395. package/dist/qualityIntelligence/retentionRoutes.d.ts +8 -0
  396. package/dist/qualityIntelligence/retentionRoutes.d.ts.map +1 -0
  397. package/dist/qualityIntelligence/retentionRoutes.js +74 -0
  398. package/dist/qualityIntelligence/reviewRoutes.d.ts +5 -0
  399. package/dist/qualityIntelligence/reviewRoutes.d.ts.map +1 -0
  400. package/dist/qualityIntelligence/reviewRoutes.js +145 -0
  401. package/dist/qualityIntelligence/reviewStore.d.ts +75 -0
  402. package/dist/qualityIntelligence/reviewStore.d.ts.map +1 -0
  403. package/dist/qualityIntelligence/reviewStore.js +170 -0
  404. package/dist/qualityIntelligence/runExecution.d.ts +36 -0
  405. package/dist/qualityIntelligence/runExecution.d.ts.map +1 -0
  406. package/dist/qualityIntelligence/runExecution.js +180 -0
  407. package/dist/qualityIntelligence/runIngestion.d.ts +70 -0
  408. package/dist/qualityIntelligence/runIngestion.d.ts.map +1 -0
  409. package/dist/qualityIntelligence/runIngestion.js +1235 -0
  410. package/dist/qualityIntelligence/runRegistry.d.ts +31 -0
  411. package/dist/qualityIntelligence/runRegistry.d.ts.map +1 -0
  412. package/dist/qualityIntelligence/runRegistry.js +66 -0
  413. package/dist/qualityIntelligence/runRoutes.d.ts +16 -0
  414. package/dist/qualityIntelligence/runRoutes.d.ts.map +1 -0
  415. package/dist/qualityIntelligence/runRoutes.js +357 -0
  416. package/dist/qualityIntelligence/traceabilityRoutes.d.ts +5 -0
  417. package/dist/qualityIntelligence/traceabilityRoutes.d.ts.map +1 -0
  418. package/dist/qualityIntelligence/traceabilityRoutes.js +173 -0
  419. package/dist/qualityIntelligence/uiRoutes.d.ts +7 -0
  420. package/dist/qualityIntelligence/uiRoutes.d.ts.map +1 -0
  421. package/dist/qualityIntelligence/uiRoutes.js +336 -0
  422. package/dist/read-handlers.d.ts +9 -0
  423. package/dist/read-handlers.d.ts.map +1 -0
  424. package/dist/read-handlers.js +265 -0
  425. package/dist/relationship-handlers.d.ts +191 -0
  426. package/dist/relationship-handlers.d.ts.map +1 -0
  427. package/dist/relationship-handlers.js +0 -0
  428. package/dist/routes.d.ts +37 -0
  429. package/dist/routes.d.ts.map +1 -0
  430. package/dist/routes.js +507 -0
  431. package/dist/run-engine.d.ts +25 -0
  432. package/dist/run-engine.d.ts.map +1 -0
  433. package/dist/run-engine.js +385 -0
  434. package/dist/run-handlers.d.ts +9 -0
  435. package/dist/run-handlers.d.ts.map +1 -0
  436. package/dist/run-handlers.js +465 -0
  437. package/dist/run-request.d.ts +17 -0
  438. package/dist/run-request.d.ts.map +1 -0
  439. package/dist/run-request.js +219 -0
  440. package/dist/runs.d.ts +47 -0
  441. package/dist/runs.d.ts.map +1 -0
  442. package/dist/runs.js +100 -0
  443. package/dist/server.d.ts +13 -0
  444. package/dist/server.d.ts.map +1 -0
  445. package/dist/server.js +152 -0
  446. package/dist/sink.d.ts +28 -0
  447. package/dist/sink.d.ts.map +1 -0
  448. package/dist/sink.js +80 -0
  449. package/dist/sse-write.d.ts +9 -0
  450. package/dist/sse-write.d.ts.map +1 -0
  451. package/dist/sse-write.js +26 -0
  452. package/dist/sse.d.ts +8 -0
  453. package/dist/sse.d.ts.map +1 -0
  454. package/dist/sse.js +27 -0
  455. package/dist/static.d.ts +5 -0
  456. package/dist/static.d.ts.map +1 -0
  457. package/dist/static.js +76 -0
  458. package/dist/store/chats.d.ts +17 -0
  459. package/dist/store/chats.d.ts.map +1 -0
  460. package/dist/store/chats.js +624 -0
  461. package/dist/store/db.d.ts +11 -0
  462. package/dist/store/db.d.ts.map +1 -0
  463. package/dist/store/db.js +203 -0
  464. package/dist/store/errors.d.ts +13 -0
  465. package/dist/store/errors.d.ts.map +1 -0
  466. package/dist/store/errors.js +30 -0
  467. package/dist/store/index.d.ts +7 -0
  468. package/dist/store/index.d.ts.map +1 -0
  469. package/dist/store/index.js +6 -0
  470. package/dist/store/messages.d.ts +8 -0
  471. package/dist/store/messages.d.ts.map +1 -0
  472. package/dist/store/messages.js +149 -0
  473. package/dist/store/paths.d.ts +5 -0
  474. package/dist/store/paths.d.ts.map +1 -0
  475. package/dist/store/paths.js +84 -0
  476. package/dist/store/projects.d.ts +8 -0
  477. package/dist/store/projects.d.ts.map +1 -0
  478. package/dist/store/projects.js +59 -0
  479. package/dist/store/relationship-audit.d.ts +42 -0
  480. package/dist/store/relationship-audit.d.ts.map +1 -0
  481. package/dist/store/relationship-audit.js +155 -0
  482. package/dist/store/relationships.d.ts +191 -0
  483. package/dist/store/relationships.d.ts.map +1 -0
  484. package/dist/store/relationships.js +724 -0
  485. package/dist/store/schema.d.ts +4 -0
  486. package/dist/store/schema.d.ts.map +1 -0
  487. package/dist/store/schema.js +220 -0
  488. package/dist/store/types.d.ts +29 -0
  489. package/dist/store/types.d.ts.map +1 -0
  490. package/dist/store/types.js +8 -0
  491. package/dist/store/validation.d.ts +7 -0
  492. package/dist/store/validation.d.ts.map +1 -0
  493. package/dist/store/validation.js +117 -0
  494. package/dist/store-handlers.d.ts +17 -0
  495. package/dist/store-handlers.d.ts.map +1 -0
  496. package/dist/store-handlers.js +872 -0
  497. package/dist/terminal-errors.d.ts +22 -0
  498. package/dist/terminal-errors.d.ts.map +1 -0
  499. package/dist/terminal-errors.js +45 -0
  500. package/dist/terminal-evidence.d.ts +21 -0
  501. package/dist/terminal-evidence.d.ts.map +1 -0
  502. package/dist/terminal-evidence.js +65 -0
  503. package/dist/terminal-routes.d.ts +10 -0
  504. package/dist/terminal-routes.d.ts.map +1 -0
  505. package/dist/terminal-routes.js +219 -0
  506. package/dist/terminal.d.ts +68 -0
  507. package/dist/terminal.d.ts.map +1 -0
  508. package/dist/terminal.js +855 -0
  509. package/package.json +52 -0
@@ -0,0 +1,70 @@
1
+ // Figma HTTP seam (Epic #750, Issue #751).
2
+ //
3
+ // The core connector NEVER calls `fetch`/undici directly. It depends only on this small
4
+ // injectable port so unit tests can mock the transport and a future proxy-aware /
5
+ // custom-CA client (#802) can be slotted in without touching connector logic.
6
+ //
7
+ // The request type intentionally carries the outbound headers (including the
8
+ // `X-Figma-Token` auth header). The token is materialised into that header ONLY by the
9
+ // default adapter below, immediately before the platform `fetch` call — it is never
10
+ // logged here and never re-emitted by the port.
11
+ //
12
+ // redirect: "manual" is set so the PAT auth header can never silently follow a
13
+ // cross-origin redirect. A 3xx response surfaces as a non-2xx status; the connector
14
+ // layer treats any non-2xx as an upstream error.
15
+ import { classifyFigmaTransportError, FigmaConnectorError } from "./figmaConnectorErrors.js";
16
+ import { gatewayFetch, readJsonCapped, } from "@oscharko-dev/keiko-model-gateway/internal/http";
17
+ /** Default request timeout in milliseconds for Figma HTTP API calls. */
18
+ const DEFAULT_TIMEOUT_MS = 60_000;
19
+ /** Default maximum JSON response body size (10 MiB). */
20
+ const DEFAULT_MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
21
+ // Collects the response headers into a plain lower-cased map. `Headers` already lower-cases
22
+ // names, so this is a faithful, allocation-bounded copy with no token (request-only header).
23
+ const collectHeaders = (response) => {
24
+ const out = {};
25
+ response.headers.forEach((value, name) => {
26
+ out[name] = value;
27
+ });
28
+ return out;
29
+ };
30
+ /**
31
+ * Thin default adapter over the platform `fetch`. This is the ONLY place `fetch` is named.
32
+ * It forwards the caller-built headers verbatim and reads the body as JSON with an explicit
33
+ * byte cap; it does not log, retry, or inspect the token. Resilience/backoff is out of scope
34
+ * here (#759); the proxy/custom-CA transport is the platform prerequisite (#802) that replaces
35
+ * this adapter.
36
+ *
37
+ * `redirect: "manual"` prevents the PAT auth header from following a cross-origin redirect.
38
+ * A 3xx response surfaces as a non-2xx port result; the connector treats non-2xx as upstream error.
39
+ */
40
+ export const createDefaultFigmaHttpPort = (egress, fetchImpl, options) => {
41
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
42
+ const maxResponseBytes = options?.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
43
+ return async (request) => {
44
+ const signal = AbortSignal.timeout(timeoutMs);
45
+ try {
46
+ const response = await gatewayFetch(request.url, {
47
+ method: "GET",
48
+ headers: { ...request.headers },
49
+ redirect: "manual",
50
+ signal,
51
+ ...(egress !== undefined ? { egress } : {}),
52
+ ...(fetchImpl !== undefined ? { fetchImpl } : {}),
53
+ });
54
+ const headers = collectHeaders(response);
55
+ let json;
56
+ try {
57
+ json = await readJsonCapped(response, maxResponseBytes);
58
+ }
59
+ catch {
60
+ throw new FigmaConnectorError("FIGMA_RESPONSE_TOO_LARGE");
61
+ }
62
+ return { status: response.status, json, headers };
63
+ }
64
+ catch (err) {
65
+ if (err instanceof FigmaConnectorError)
66
+ throw err;
67
+ throw new FigmaConnectorError(classifyFigmaTransportError(err));
68
+ }
69
+ };
70
+ };
@@ -0,0 +1,49 @@
1
+ import { type FigmaAugmentationTally, type FigmaConnectorMetrics, type FigmaConnectorMetricsExtras } from "./figmaConnectorMetrics.js";
2
+ import { type FigmaScopeRef } from "./figmaScopeRef.js";
3
+ import type { FigmaProvenance } from "./figmaConnector.js";
4
+ import type { FigmaSnapshot } from "./figmaSnapshotTypes.js";
5
+ import type { QualityIntelligenceFigma } from "@oscharko-dev/keiko-quality-intelligence";
6
+ export interface ObservedActionContext {
7
+ readonly evidenceDir: string;
8
+ readonly now: string;
9
+ }
10
+ export interface ObservedSnapshotInput {
11
+ readonly ctx: ObservedActionContext;
12
+ /** Token-free provenance from the connector fetch — the scopeRef source. */
13
+ readonly provenance: FigmaProvenance;
14
+ readonly ir: QualityIntelligenceFigma.ScreenIrResult;
15
+ readonly augmentation: FigmaAugmentationTally;
16
+ readonly extras?: FigmaConnectorMetricsExtras;
17
+ /** `true` for a re-snapshot action, `false`/omitted for an initial snapshot. */
18
+ readonly isResnapshot?: boolean;
19
+ /**
20
+ * Defaults to true. Route orchestration sets this false so success is audited only after the
21
+ * snapshot record has been durably written and reloaded from Evidence.
22
+ */
23
+ readonly auditSuccess?: boolean;
24
+ /** Performs the actual render + assembly (delegates to buildFigmaSnapshot / resnapshotFigma). */
25
+ readonly run: () => Promise<FigmaSnapshot>;
26
+ }
27
+ export interface ObservedSnapshotResult {
28
+ readonly snapshot: FigmaSnapshot;
29
+ readonly metrics: FigmaConnectorMetrics;
30
+ readonly scopeRef: FigmaScopeRef;
31
+ }
32
+ /**
33
+ * Observe a snapshot or re-snapshot: gate on consent, run the build, then audit (with counts) and
34
+ * compute metrics on success, or audit the coded failure and re-raise. The build itself is injected
35
+ * so no #753/#759 behaviour changes.
36
+ */
37
+ export declare const observeFigmaSnapshot: (input: ObservedSnapshotInput) => Promise<ObservedSnapshotResult>;
38
+ export interface ObservedRevokeInput {
39
+ readonly ctx: ObservedActionContext;
40
+ readonly scopeRef: FigmaScopeRef;
41
+ /** Performs the actual key removal (delegates to FigmaTokenStore.revoke). */
42
+ readonly run: () => void;
43
+ }
44
+ /**
45
+ * Observe a revoke (key removal): run it, then audit the action. Revoke needs no consent gate — it
46
+ * removes access — and produces no metrics. A failure is audited then re-raised.
47
+ */
48
+ export declare const observeFigmaRevoke: (input: ObservedRevokeInput) => void;
49
+ //# sourceMappingURL=figmaObservedActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaObservedActions.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaObservedActions.ts"],"names":[],"mappings":"AAoBA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EACjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAEzF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAmCD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,qBAAqB,CAAC;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC,cAAc,CAAC;IACrD,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,2BAA2B,CAAC;IAC9C,gFAAgF;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,iGAAiG;IACjG,QAAQ,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,qBAAqB,KAC3B,OAAO,CAAC,sBAAsB,CA+BhC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,qBAAqB,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,mBAAmB,KAAG,IAa/D,CAAC"}
@@ -0,0 +1,89 @@
1
+ // Observed connector actions — the audit/consent/metrics hook points (Epic #750, Issue #760).
2
+ //
3
+ // PURELY ADDITIVE over #751/#753/#758/#759: this module does NOT change the connector, snapshot
4
+ // builder, re-snapshot, or token-store behaviour. It composes them with the three governance
5
+ // concerns so the future route tier (#756) calls ONE function per action and gets:
6
+ // - consent gating before the FIRST fetch (connect / snapshot / resnapshot),
7
+ // - an audit entry on success AND on a coded failure (re-raising the original error),
8
+ // - operational metrics on a successful snapshot / re-snapshot.
9
+ //
10
+ // The scopeRef is derived from the connector's token-free provenance, so no board id / link ever
11
+ // reaches the audit or metrics. The actual board fetch is delegated to the injected action; this
12
+ // wrapper only observes it.
13
+ import { FigmaConnectorError } from "./figmaConnectorErrors.js";
14
+ import { appendFigmaConnectorAudit, } from "./figmaConnectorAudit.js";
15
+ import { assertReadOnlyConsent } from "./figmaConsent.js";
16
+ import { computeFigmaConnectorMetrics, } from "./figmaConnectorMetrics.js";
17
+ import { deriveFigmaScopeRef } from "./figmaScopeRef.js";
18
+ const auditFailureAndRethrow = (ctx, scopeRef, action, error) => {
19
+ const errorCode = error instanceof FigmaConnectorError ? error.code : "FIGMA_INTERNAL";
20
+ appendFigmaConnectorAudit({
21
+ scopeRef,
22
+ evidenceDir: ctx.evidenceDir,
23
+ action,
24
+ outcome: "error",
25
+ errorCode,
26
+ now: ctx.now,
27
+ });
28
+ throw error;
29
+ };
30
+ const countsOf = (ir, snapshot) => ({
31
+ screens: ir.screens.length,
32
+ renders: snapshot.screens.length,
33
+ skipped: snapshot.skippedScreens.length,
34
+ designTokens: ir.tokens.colors.length +
35
+ ir.tokens.typography.length +
36
+ ir.tokens.spacing.length +
37
+ ir.tokens.radius.length,
38
+ ...(ir.links.length > 0 ? { navTransitions: ir.links.length } : {}),
39
+ });
40
+ /**
41
+ * Observe a snapshot or re-snapshot: gate on consent, run the build, then audit (with counts) and
42
+ * compute metrics on success, or audit the coded failure and re-raise. The build itself is injected
43
+ * so no #753/#759 behaviour changes.
44
+ */
45
+ export const observeFigmaSnapshot = async (input) => {
46
+ const scopeRef = deriveFigmaScopeRef(input.provenance.fileKey, input.provenance.nodeId);
47
+ const action = input.isResnapshot === true ? "resnapshot" : "snapshot";
48
+ // Consent is a precondition checked BEFORE the action starts, so a consent-denied attempt throws
49
+ // here and produces no audit entry: it is a refused precondition, not a connector-action outcome.
50
+ assertReadOnlyConsent(scopeRef, input.ctx.evidenceDir);
51
+ let snapshot;
52
+ try {
53
+ snapshot = await input.run();
54
+ }
55
+ catch (error) {
56
+ return auditFailureAndRethrow(input.ctx, scopeRef, action, error);
57
+ }
58
+ const metrics = computeFigmaConnectorMetrics(input.ir, snapshot, input.augmentation, input.extras ?? {});
59
+ if (input.auditSuccess !== false) {
60
+ appendFigmaConnectorAudit({
61
+ scopeRef,
62
+ evidenceDir: input.ctx.evidenceDir,
63
+ action,
64
+ outcome: "ok",
65
+ counts: countsOf(input.ir, snapshot),
66
+ now: input.ctx.now,
67
+ });
68
+ }
69
+ return { snapshot, metrics, scopeRef };
70
+ };
71
+ /**
72
+ * Observe a revoke (key removal): run it, then audit the action. Revoke needs no consent gate — it
73
+ * removes access — and produces no metrics. A failure is audited then re-raised.
74
+ */
75
+ export const observeFigmaRevoke = (input) => {
76
+ try {
77
+ input.run();
78
+ }
79
+ catch (error) {
80
+ auditFailureAndRethrow(input.ctx, input.scopeRef, "revoke", error);
81
+ }
82
+ appendFigmaConnectorAudit({
83
+ scopeRef: input.scopeRef,
84
+ evidenceDir: input.ctx.evidenceDir,
85
+ action: "revoke",
86
+ outcome: "ok",
87
+ now: input.ctx.now,
88
+ });
89
+ };
@@ -0,0 +1,32 @@
1
+ export interface FigmaDevStatus {
2
+ readonly type: string;
3
+ }
4
+ export interface FigmaNode {
5
+ readonly id: string;
6
+ readonly name: string;
7
+ readonly type: string;
8
+ readonly devStatus?: FigmaDevStatus;
9
+ readonly children?: readonly FigmaNode[];
10
+ }
11
+ export interface ReadinessOptions {
12
+ readonly version?: string | undefined;
13
+ readonly releaseMarker?: string | undefined;
14
+ }
15
+ export type ReadinessSignal = {
16
+ readonly source: "version";
17
+ readonly ready: true;
18
+ readonly version: string;
19
+ } | {
20
+ readonly source: "section";
21
+ readonly ready: true;
22
+ readonly matchedNodeName: string;
23
+ } | {
24
+ readonly source: "devStatus";
25
+ readonly ready: true;
26
+ readonly readyNodeCount: number;
27
+ } | {
28
+ readonly source: "none";
29
+ readonly ready: false;
30
+ };
31
+ export declare const resolveReadiness: (root: FigmaNode, options: ReadinessOptions) => ReadinessSignal;
32
+ //# sourceMappingURL=figmaReadiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaReadiness.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaReadiness.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GACtF;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AA2CvD,eAAO,MAAM,gBAAgB,GAAI,MAAM,SAAS,EAAE,SAAS,gBAAgB,KAAG,eAiB7E,CAAC"}
@@ -0,0 +1,67 @@
1
+ // Figma readiness resolution (Epic #750, Issue #751).
2
+ //
3
+ // Pure, deterministic. Resolves whether a scoped node subtree is "release-ready" using a
4
+ // fixed precedence with graceful fallback:
5
+ //
6
+ // 1. version — a pinned version id was supplied (operator pinned a named version).
7
+ // 2. section — a node anywhere in the subtree is named with a configurable release
8
+ // marker (default case-insensitive token `release`).
9
+ // 3. devStatus — one or more nodes carry Dev-Mode `devStatus.type === "READY_FOR_DEV"`.
10
+ //
11
+ // `devStatus` is OPTIONAL in the Figma REST response and may be absent for an entire
12
+ // account/plan. When it is absent (or no node is READY_FOR_DEV) and the higher signals
13
+ // did not fire, the result degrades to `{ source: "none", ready: false }`.
14
+ const DEFAULT_RELEASE_MARKER = "release";
15
+ const READY_FOR_DEV = "READY_FOR_DEV";
16
+ const TOKEN_SPLIT = /[^a-z0-9]+/u;
17
+ const NEGATED_RELEASE_NAME = /\b(?:unreleased|not\s+(?:for\s+)?release|no\s+release|non[-\s]+release)\b/iu;
18
+ const walk = (node, visit) => {
19
+ if (visit(node))
20
+ return true;
21
+ for (const child of node.children ?? []) {
22
+ if (walk(child, visit))
23
+ return true;
24
+ }
25
+ return false;
26
+ };
27
+ const findReleaseNamedNode = (root, marker) => {
28
+ const needle = marker.trim().toLowerCase();
29
+ if (needle.length === 0)
30
+ return undefined;
31
+ let match;
32
+ walk(root, (node) => {
33
+ const lowerName = node.name.toLowerCase();
34
+ const tokens = lowerName.split(TOKEN_SPLIT).filter((token) => token.length > 0);
35
+ const markerMatched = tokens.includes(needle) || (needle === DEFAULT_RELEASE_MARKER && tokens.includes("released"));
36
+ if (markerMatched && !NEGATED_RELEASE_NAME.test(lowerName)) {
37
+ match = node;
38
+ return true;
39
+ }
40
+ return false;
41
+ });
42
+ return match;
43
+ };
44
+ const countReadyForDevNodes = (root) => {
45
+ let count = 0;
46
+ walk(root, (node) => {
47
+ if (node.devStatus?.type === READY_FOR_DEV)
48
+ count += 1;
49
+ return false;
50
+ });
51
+ return count;
52
+ };
53
+ export const resolveReadiness = (root, options) => {
54
+ if (options.version !== undefined && options.version.length > 0) {
55
+ return { source: "version", ready: true, version: options.version };
56
+ }
57
+ const marker = options.releaseMarker ?? DEFAULT_RELEASE_MARKER;
58
+ const namedNode = findReleaseNamedNode(root, marker);
59
+ if (namedNode !== undefined) {
60
+ return { source: "section", ready: true, matchedNodeName: namedNode.name };
61
+ }
62
+ const readyNodeCount = countReadyForDevNodes(root);
63
+ if (readyNodeCount > 0) {
64
+ return { source: "devStatus", ready: true, readyNodeCount };
65
+ }
66
+ return { source: "none", ready: false };
67
+ };
@@ -0,0 +1,29 @@
1
+ import { type OutboundHttpEgressConfig } from "@oscharko-dev/keiko-model-gateway/internal/http";
2
+ export interface FigmaRenderRequest {
3
+ readonly url: string;
4
+ readonly headers: Readonly<Record<string, string>>;
5
+ }
6
+ export interface FigmaRenderResponse {
7
+ readonly status: number;
8
+ readonly bytes: Uint8Array;
9
+ readonly headers: Readonly<Record<string, string>>;
10
+ }
11
+ export type FigmaRenderPort = (request: FigmaRenderRequest) => Promise<FigmaRenderResponse>;
12
+ /** Optional creation-time overrides for the default render port. */
13
+ export interface FigmaRenderPortOptions {
14
+ readonly timeoutMs?: number;
15
+ readonly maxResponseBytes?: number;
16
+ }
17
+ /**
18
+ * Thin default adapter over the platform `fetch`. This is the ONLY place in the render path
19
+ * `fetch` is named. It forwards the caller-built headers verbatim and reads the body as raw
20
+ * bytes with an explicit byte cap; it does not log, retry, or inspect any token. Resilience/
21
+ * backoff is out of scope here (#759); the proxy/custom-CA transport is the platform
22
+ * prerequisite (#802) that replaces this.
23
+ *
24
+ * `redirect: "manual"` prevents any caller-supplied auth header from following a cross-origin
25
+ * redirect. A 3xx response surfaces as a non-2xx port result; the connector treats it as
26
+ * upstream error.
27
+ */
28
+ export declare const createDefaultFigmaRenderPort: (egress?: OutboundHttpEgressConfig, fetchImpl?: typeof fetch, options?: FigmaRenderPortOptions) => FigmaRenderPort;
29
+ //# sourceMappingURL=figmaRenderPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaRenderPort.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaRenderPort.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,iDAAiD,CAAC;AAQzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAG3B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAE5F,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAiCD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,GACvC,SAAS,wBAAwB,EACjC,YAAY,OAAO,KAAK,EACxB,UAAU,sBAAsB,KAC/B,eA2BF,CAAC"}
@@ -0,0 +1,93 @@
1
+ // Figma render-byte seam (Epic #750, Issue #753).
2
+ //
3
+ // The `/v1/images` API returns an EPHEMERAL https url per rendered frame; a SECOND fetch
4
+ // downloads the PNG bytes from that url. The snapshot builder NEVER calls `fetch`/undici
5
+ // directly for that download — it depends only on this small injectable port so unit tests
6
+ // can mock the transport and a future proxy-aware / custom-CA client (#802) can be slotted in
7
+ // without touching builder logic.
8
+ //
9
+ // The request type carries the outbound headers. The render-url download itself needs no
10
+ // Figma auth header (the ephemeral url is pre-signed), but the seam still forwards whatever
11
+ // headers the caller supplies so the proxy adapter can add transport headers. The token is
12
+ // never materialised here and never logged.
13
+ //
14
+ // redirect: "manual" is set so any auth header supplied by the caller cannot follow a
15
+ // cross-origin redirect. A 3xx response surfaces as a non-2xx status; the connector
16
+ // layer treats non-2xx as upstream error.
17
+ import { classifyFigmaTransportError, FigmaConnectorError } from "./figmaConnectorErrors.js";
18
+ import { gatewayFetch, } from "@oscharko-dev/keiko-model-gateway/internal/http";
19
+ /** Default request timeout in milliseconds for Figma render downloads. */
20
+ const DEFAULT_TIMEOUT_MS = 60_000;
21
+ /** Default maximum render response body size (32 MiB). */
22
+ const DEFAULT_MAX_RESPONSE_BYTES = 32 * 1024 * 1024;
23
+ /**
24
+ * Read a streaming response body up to `maxBytes`, accumulating into a Uint8Array.
25
+ * Throws a {@link FigmaConnectorError} with `FIGMA_RESPONSE_TOO_LARGE` if the cap is exceeded.
26
+ */
27
+ const readBytesCapped = async (response, maxBytes) => {
28
+ if (response.body === null) {
29
+ const buffer = await response.arrayBuffer();
30
+ return new Uint8Array(buffer);
31
+ }
32
+ const reader = response.body.getReader();
33
+ const chunks = [];
34
+ let total = 0;
35
+ for (;;) {
36
+ const { done, value } = await reader.read();
37
+ if (done)
38
+ break;
39
+ total += value.byteLength;
40
+ if (total > maxBytes) {
41
+ await reader.cancel();
42
+ throw new FigmaConnectorError("FIGMA_RESPONSE_TOO_LARGE");
43
+ }
44
+ chunks.push(value);
45
+ }
46
+ const out = new Uint8Array(total);
47
+ let offset = 0;
48
+ for (const chunk of chunks) {
49
+ out.set(chunk, offset);
50
+ offset += chunk.byteLength;
51
+ }
52
+ return out;
53
+ };
54
+ /**
55
+ * Thin default adapter over the platform `fetch`. This is the ONLY place in the render path
56
+ * `fetch` is named. It forwards the caller-built headers verbatim and reads the body as raw
57
+ * bytes with an explicit byte cap; it does not log, retry, or inspect any token. Resilience/
58
+ * backoff is out of scope here (#759); the proxy/custom-CA transport is the platform
59
+ * prerequisite (#802) that replaces this.
60
+ *
61
+ * `redirect: "manual"` prevents any caller-supplied auth header from following a cross-origin
62
+ * redirect. A 3xx response surfaces as a non-2xx port result; the connector treats it as
63
+ * upstream error.
64
+ */
65
+ export const createDefaultFigmaRenderPort = (egress, fetchImpl, options) => {
66
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
67
+ const maxResponseBytes = options?.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
68
+ return async (request) => {
69
+ const signal = AbortSignal.timeout(timeoutMs);
70
+ try {
71
+ const response = await gatewayFetch(request.url, {
72
+ method: "GET",
73
+ headers: { ...request.headers },
74
+ redirect: "manual",
75
+ signal,
76
+ maxResponseBytes,
77
+ ...(egress !== undefined ? { egress } : {}),
78
+ ...(fetchImpl !== undefined ? { fetchImpl } : {}),
79
+ });
80
+ const headers = {};
81
+ response.headers.forEach((value, name) => {
82
+ headers[name] = value;
83
+ });
84
+ const bytes = await readBytesCapped(response, maxResponseBytes);
85
+ return { status: response.status, bytes, headers };
86
+ }
87
+ catch (err) {
88
+ if (err instanceof FigmaConnectorError)
89
+ throw err;
90
+ throw new FigmaConnectorError(classifyFigmaTransportError(err));
91
+ }
92
+ };
93
+ };
@@ -0,0 +1,28 @@
1
+ import type { FigmaConnector, FigmaFetchOptions } from "./figmaConnector.js";
2
+ import type { FigmaHttpPort } from "./figmaHttpPort.js";
3
+ import type { FigmaRenderPort } from "./figmaRenderPort.js";
4
+ import type { FigmaSnapshot } from "./figmaSnapshotTypes.js";
5
+ import type { FigmaRetryPolicy, FigmaRetrySleep } from "./figmaRetry.js";
6
+ import type { FigmaScopedResult } from "./figmaConnector.js";
7
+ import type { QualityIntelligenceFigma } from "@oscharko-dev/keiko-quality-intelligence";
8
+ /** Deterministic clean of the raw scoped nodes into the per-screen IR (#752 lives behind this seam). */
9
+ export type FigmaCleanToIr = (scoped: FigmaScopedResult) => QualityIntelligenceFigma.ScreenIrResult;
10
+ export interface ResnapshotFigmaDeps {
11
+ readonly connector: FigmaConnector;
12
+ readonly cleanToIr: FigmaCleanToIr;
13
+ readonly token: string;
14
+ readonly imagesPort: FigmaHttpPort;
15
+ readonly renderPort: FigmaRenderPort;
16
+ readonly batchSize?: number;
17
+ readonly maxImageBytes?: number;
18
+ readonly downloadConcurrency?: number;
19
+ readonly retryPolicy?: FigmaRetryPolicy;
20
+ readonly sleep?: FigmaRetrySleep;
21
+ }
22
+ /**
23
+ * Perform an explicit full scoped re-snapshot of `url`. Re-fetches the whole scope and rebuilds
24
+ * the Snapshot — no delta, no incremental reuse. `options.version` pins the re-fetch to a named
25
+ * Figma version so the re-snapshot stays within the configured scope.
26
+ */
27
+ export declare const resnapshotFigma: (url: string, deps: ResnapshotFigmaDeps, options?: FigmaFetchOptions) => Promise<FigmaSnapshot>;
28
+ //# sourceMappingURL=figmaResnapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaResnapshot.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaResnapshot.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAEzF,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,wBAAwB,CAAC,cAAc,CAAC;AAEpG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,MAAM,EACX,MAAM,mBAAmB,EACzB,UAAS,iBAAsB,KAC9B,OAAO,CAAC,aAAa,CAuBvB,CAAC"}
@@ -0,0 +1,38 @@
1
+ // Explicit, on-demand FULL re-snapshot of a Figma scope (Epic #750, Issue #759; drift #735).
2
+ //
3
+ // A re-snapshot is a DELIBERATE caller action — never a webhook, never a poll, never a designer
4
+ // signal. It performs a fresh, scoped, FULL re-fetch of the same board scope and rebuilds the
5
+ // immutable Snapshot from scratch: scoped nodes fetch → deterministic IR clean → render. There is
6
+ // NO delta and NO incremental skip of "unchanged" screens — every screen in scope is re-fetched
7
+ // and re-rendered. Because the Snapshot integrity hash is deterministic and excludes wall-clock
8
+ // time, two re-snapshots of an unchanged design hash identically; a changed design changes the
9
+ // hash. That hash compare IS the drift signal (#735) — this module performs the re-snapshot; the
10
+ // comparison is the caller's, and Figma is contacted ONLY here, within the snapshot boundary.
11
+ import { buildFigmaSnapshot } from "./figmaSnapshotBuilder.js";
12
+ /**
13
+ * Perform an explicit full scoped re-snapshot of `url`. Re-fetches the whole scope and rebuilds
14
+ * the Snapshot — no delta, no incremental reuse. `options.version` pins the re-fetch to a named
15
+ * Figma version so the re-snapshot stays within the configured scope.
16
+ */
17
+ export const resnapshotFigma = async (url, deps, options = {}) => {
18
+ // Deep scoped-pagination fetch (#837): a re-snapshot must capture the same in-screen text the
19
+ // initial build does, so the regenerated drift baseline (#735) is comparable. Still a FULL,
20
+ // explicit, on-demand re-fetch — no delta, no incremental skip — within the snapshot boundary.
21
+ const scoped = await deps.connector.fetchScopedNodesDeep(url, options);
22
+ const ir = deps.cleanToIr(scoped);
23
+ const buildInput = {
24
+ ir,
25
+ provenance: scoped.provenance,
26
+ token: deps.token,
27
+ imagesPort: deps.imagesPort,
28
+ renderPort: deps.renderPort,
29
+ ...(deps.batchSize !== undefined ? { batchSize: deps.batchSize } : {}),
30
+ ...(deps.maxImageBytes !== undefined ? { maxImageBytes: deps.maxImageBytes } : {}),
31
+ ...(deps.downloadConcurrency !== undefined
32
+ ? { downloadConcurrency: deps.downloadConcurrency }
33
+ : {}),
34
+ ...(deps.retryPolicy !== undefined ? { retryPolicy: deps.retryPolicy } : {}),
35
+ ...(deps.sleep !== undefined ? { sleep: deps.sleep } : {}),
36
+ };
37
+ return buildFigmaSnapshot(buildInput);
38
+ };
@@ -0,0 +1,31 @@
1
+ /** Injectable wait seam — the default is real `setTimeout`; tests pass a synchronous recorder. */
2
+ export type FigmaRetrySleep = (ms: number) => Promise<void>;
3
+ export interface FigmaRetryPolicy {
4
+ /** Maximum extra attempts after the first; total attempts = maxRetries + 1. */
5
+ readonly maxRetries: number;
6
+ /** First backoff delay in ms; subsequent delays double until `maxDelayMs`. */
7
+ readonly baseDelayMs: number;
8
+ /** Hard ceiling for any single delay (computed or `Retry-After`) — prevents unbounded waits. */
9
+ readonly maxDelayMs: number;
10
+ }
11
+ /**
12
+ * Bounded, conservative default well inside Figma's documented limits. Patient enough (8 retries,
13
+ * 45s ceiling) that the multi-fetch deep scoped-pagination build (#837) absorbs the cost-based 429
14
+ * bursts a large board provokes instead of aborting, while staying finite so a genuinely down API
15
+ * still fails fast-ish.
16
+ */
17
+ export declare const DEFAULT_FIGMA_RETRY_POLICY: FigmaRetryPolicy;
18
+ /** The minimum a backoff-capable response must expose: a status and (lower-cased) headers. */
19
+ export interface FigmaBackoffResponse {
20
+ readonly status: number;
21
+ readonly headers?: Readonly<Record<string, string>>;
22
+ }
23
+ /** The real-timer sleep used by the default ports. */
24
+ export declare const realFigmaRetrySleep: FigmaRetrySleep;
25
+ /**
26
+ * Run `operation` (a single attempt), retrying ONLY on HTTP 429 with deterministic exponential
27
+ * backoff up to `policy.maxRetries`. Honours a numeric `Retry-After` over the computed delay.
28
+ * Throws FIGMA_RATE_LIMITED once the bounded retries are exhausted; never retries a non-429.
29
+ */
30
+ export declare const fetchWithBackoff: <R extends FigmaBackoffResponse>(operation: () => Promise<R>, policy: FigmaRetryPolicy, sleep: FigmaRetrySleep) => Promise<R>;
31
+ //# sourceMappingURL=figmaRetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaRetry.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaRetry.ts"],"names":[],"mappings":"AAgBA,kGAAkG;AAClG,MAAM,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gGAAgG;IAChG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAIxC,CAAC;AAEF,8FAA8F;AAC9F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,EAAE,eAG9B,CAAC;AAsBL;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAU,CAAC,SAAS,oBAAoB,EACnE,WAAW,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,QAAQ,gBAAgB,EACxB,OAAO,eAAe,KACrB,OAAO,CAAC,CAAC,CASX,CAAC"}
@@ -0,0 +1,62 @@
1
+ // Deterministic 429 backoff for the bounded Figma snapshot-build (Epic #750, Issue #759).
2
+ //
3
+ // Figma rate-limits the scoped `/v1/files/:key/nodes` fetch and the `/v1/images` render with HTTP
4
+ // 429. On a huge enterprise board these are expected, not exceptional, so the snapshot-build must
5
+ // retry them on a deterministic exponential schedule rather than failing or hammering the API.
6
+ //
7
+ // Scope discipline: ONLY a 429 is retried here. A 4xx (auth/scope/not-found) or 5xx is surfaced
8
+ // to the caller unchanged — those are not rate-limit conditions and must not be silently retried.
9
+ // There is NO webhook, NO polling, and NO timer beyond the injectable `sleep` seam: the whole
10
+ // schedule is driven by the caller's awaited promise chain, so a mocked sleep makes tests instant.
11
+ //
12
+ // The `sleep` seam is injectable so unit tests record the exact delay schedule without waiting.
13
+ // `Retry-After` (whole seconds) is honoured when present and numeric, capped at `maxDelayMs`.
14
+ import { FigmaConnectorError } from "./figmaConnectorErrors.js";
15
+ /**
16
+ * Bounded, conservative default well inside Figma's documented limits. Patient enough (8 retries,
17
+ * 45s ceiling) that the multi-fetch deep scoped-pagination build (#837) absorbs the cost-based 429
18
+ * bursts a large board provokes instead of aborting, while staying finite so a genuinely down API
19
+ * still fails fast-ish.
20
+ */
21
+ export const DEFAULT_FIGMA_RETRY_POLICY = {
22
+ maxRetries: 8,
23
+ baseDelayMs: 500,
24
+ maxDelayMs: 45_000,
25
+ };
26
+ /** The real-timer sleep used by the default ports. */
27
+ export const realFigmaRetrySleep = (ms) => new Promise((resolve) => {
28
+ setTimeout(resolve, ms);
29
+ });
30
+ const FIGMA_RATE_LIMIT_STATUS = 429;
31
+ const computeBackoffMs = (attempt, policy) => {
32
+ const exponential = policy.baseDelayMs * 2 ** attempt;
33
+ return Math.min(exponential, policy.maxDelayMs);
34
+ };
35
+ // Parses a numeric `Retry-After` (whole seconds) into capped milliseconds. Returns undefined for a
36
+ // missing/non-numeric/negative value so the caller falls back to the computed exponential delay.
37
+ const retryAfterMs = (headers, policy) => {
38
+ const raw = headers?.["retry-after"];
39
+ if (raw === undefined)
40
+ return undefined;
41
+ const seconds = Number(raw);
42
+ if (!Number.isFinite(seconds) || seconds < 0)
43
+ return undefined;
44
+ return Math.min(seconds * 1000, policy.maxDelayMs);
45
+ };
46
+ /**
47
+ * Run `operation` (a single attempt), retrying ONLY on HTTP 429 with deterministic exponential
48
+ * backoff up to `policy.maxRetries`. Honours a numeric `Retry-After` over the computed delay.
49
+ * Throws FIGMA_RATE_LIMITED once the bounded retries are exhausted; never retries a non-429.
50
+ */
51
+ export const fetchWithBackoff = async (operation, policy, sleep) => {
52
+ for (let attempt = 0; attempt <= policy.maxRetries; attempt += 1) {
53
+ const response = await operation();
54
+ if (response.status !== FIGMA_RATE_LIMIT_STATUS)
55
+ return response;
56
+ if (attempt === policy.maxRetries)
57
+ break;
58
+ const delay = retryAfterMs(response.headers, policy) ?? computeBackoffMs(attempt, policy);
59
+ await sleep(delay);
60
+ }
61
+ throw new FigmaConnectorError("FIGMA_RATE_LIMITED");
62
+ };
@@ -0,0 +1,9 @@
1
+ /** Opaque, non-reversible reference to a connected Figma scope. Hex SHA-256, safe as a store key. */
2
+ export type FigmaScopeRef = string;
3
+ /**
4
+ * Derive the opaque scope reference for a `(fileKey, nodeId)` pair. Pure and deterministic. The
5
+ * inputs are design identifiers and are consumed ONLY to produce the one-way digest — they are not
6
+ * retained anywhere by this function.
7
+ */
8
+ export declare const deriveFigmaScopeRef: (fileKey: string, nodeId: string) => FigmaScopeRef;
9
+ //# sourceMappingURL=figmaScopeRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figmaScopeRef.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaScopeRef.ts"],"names":[],"mappings":"AAcA,qGAAqG;AACrG,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,aACnC,CAAC"}