@yadsh/dsh-qa-surface 0.16.0 → 0.18.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 (325) hide show
  1. package/README.md +34 -5
  2. package/compatibility.json +1 -1
  3. package/lib/account-remotes.js +13 -0
  4. package/lib/account-remotes.js.map +1 -1
  5. package/lib/accounts/database.js +120 -4
  6. package/lib/accounts/database.js.map +1 -1
  7. package/lib/accounts/file.js.map +1 -1
  8. package/lib/accounts/store.js +131 -5
  9. package/lib/accounts/store.js.map +1 -1
  10. package/lib/accounts/token.js +8 -2
  11. package/lib/accounts/token.js.map +1 -1
  12. package/lib/admin/metrics.js +15 -2
  13. package/lib/admin/metrics.js.map +1 -1
  14. package/lib/admin/read-budget.js +28 -0
  15. package/lib/admin/read-budget.js.map +1 -0
  16. package/lib/admin/service.js +135 -40
  17. package/lib/admin/service.js.map +1 -1
  18. package/lib/admin/session-log.js +63 -4
  19. package/lib/admin/session-log.js.map +1 -1
  20. package/lib/chat-sharing/native-fence.js +31 -2
  21. package/lib/chat-sharing/native-fence.js.map +1 -1
  22. package/lib/chat-sharing/store.js +9 -3
  23. package/lib/chat-sharing/store.js.map +1 -1
  24. package/lib/chat-sharing/transport.js +74 -13
  25. package/lib/chat-sharing/transport.js.map +1 -1
  26. package/lib/chat-sharing/uploads.js +79 -6
  27. package/lib/chat-sharing/uploads.js.map +1 -1
  28. package/lib/cli.js +13 -0
  29. package/lib/cli.js.map +1 -1
  30. package/lib/client/QaAccountsController.js +79 -0
  31. package/lib/client/QaAccountsController.js.map +1 -1
  32. package/lib/client/QaRouteController.js +3 -1
  33. package/lib/client/QaRouteController.js.map +1 -1
  34. package/lib/client/QaSessionController.js +102 -29
  35. package/lib/client/QaSessionController.js.map +1 -1
  36. package/lib/client/QaSurface.js +89 -19
  37. package/lib/client/QaSurface.js.map +1 -1
  38. package/lib/client/QaTranscriptAdapter.js +15 -2
  39. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  40. package/lib/client/account-sessions.js +74 -8
  41. package/lib/client/account-sessions.js.map +1 -1
  42. package/lib/client/admin/CapabilityPicker.js +50 -0
  43. package/lib/client/admin/CapabilityPicker.js.map +1 -0
  44. package/lib/client/admin/CoverageNotice.js +9 -0
  45. package/lib/client/admin/CoverageNotice.js.map +1 -0
  46. package/lib/client/admin/QaAdmin.js +3 -150
  47. package/lib/client/admin/QaAdmin.js.map +1 -1
  48. package/lib/client/admin/RoleEditor.js +46 -0
  49. package/lib/client/admin/RoleEditor.js.map +1 -0
  50. package/lib/client/admin/capability-selection.js +63 -0
  51. package/lib/client/admin/capability-selection.js.map +1 -0
  52. package/lib/client/admin/pages/Conversations.js +35 -17
  53. package/lib/client/admin/pages/Conversations.js.map +1 -1
  54. package/lib/client/admin/pages/Overview.js +3 -2
  55. package/lib/client/admin/pages/Overview.js.map +1 -1
  56. package/lib/client/admin/pages/Quality.js +77 -20
  57. package/lib/client/admin/pages/Quality.js.map +1 -1
  58. package/lib/client/admin/pages/SkillFiles.js +14 -3
  59. package/lib/client/admin/pages/SkillFiles.js.map +1 -1
  60. package/lib/client/admin/shared.js +68 -3
  61. package/lib/client/admin/shared.js.map +1 -1
  62. package/lib/client/answer-review.js +89 -0
  63. package/lib/client/answer-review.js.map +1 -0
  64. package/lib/client/chat-artifacts.js +1 -0
  65. package/lib/client/chat-artifacts.js.map +1 -1
  66. package/lib/client/components/QaAnswerReviewStatus.js +45 -0
  67. package/lib/client/components/QaAnswerReviewStatus.js.map +1 -0
  68. package/lib/client/components/QaAuthGate.js +31 -28
  69. package/lib/client/components/QaAuthGate.js.map +1 -1
  70. package/lib/client/components/QaChangelog.js +79 -0
  71. package/lib/client/components/QaChangelog.js.map +1 -1
  72. package/lib/client/components/QaChatActions.js +52 -0
  73. package/lib/client/components/QaChatActions.js.map +1 -0
  74. package/lib/client/components/QaChatSharing.js +22 -19
  75. package/lib/client/components/QaChatSharing.js.map +1 -1
  76. package/lib/client/components/QaComposer.js +27 -4
  77. package/lib/client/components/QaComposer.js.map +1 -1
  78. package/lib/client/components/QaFormItem.js +63 -0
  79. package/lib/client/components/QaFormItem.js.map +1 -0
  80. package/lib/client/components/QaInputForm.js +281 -0
  81. package/lib/client/components/QaInputForm.js.map +1 -0
  82. package/lib/client/components/QaMarkdownPreview.js +86 -0
  83. package/lib/client/components/QaMarkdownPreview.js.map +1 -0
  84. package/lib/client/components/QaMessage.js +8 -2
  85. package/lib/client/components/QaMessage.js.map +1 -1
  86. package/lib/client/components/QaModal.js +34 -4
  87. package/lib/client/components/QaModal.js.map +1 -1
  88. package/lib/client/components/QaRightRail.js +6 -4
  89. package/lib/client/components/QaRightRail.js.map +1 -1
  90. package/lib/client/components/QaRightRailResize.js +129 -0
  91. package/lib/client/components/QaRightRailResize.js.map +1 -0
  92. package/lib/client/components/QaSidebar.js +10 -1
  93. package/lib/client/components/QaSidebar.js.map +1 -1
  94. package/lib/client/components/QaSourceFilters.js +22 -0
  95. package/lib/client/components/QaSourceFilters.js.map +1 -0
  96. package/lib/client/components/QaSourcesPanel.js +57 -13
  97. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  98. package/lib/client/components/QaSpreadsheetPreview.js +56 -0
  99. package/lib/client/components/QaSpreadsheetPreview.js.map +1 -0
  100. package/lib/client/components/QaWelcomeNotice.js +2 -2
  101. package/lib/client/components/QaWelcomeNotice.js.map +1 -1
  102. package/lib/client/components/QaWorkspaceBrowser.js +22 -9
  103. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
  104. package/lib/client/components/QaZoomImage.js +56 -0
  105. package/lib/client/components/QaZoomImage.js.map +1 -0
  106. package/lib/client/components/source-refs.js +18 -4
  107. package/lib/client/components/source-refs.js.map +1 -1
  108. package/lib/client/forms-styles.js +14 -0
  109. package/lib/client/forms-styles.js.map +1 -0
  110. package/lib/client/forms.js +40 -0
  111. package/lib/client/forms.js.map +1 -0
  112. package/lib/client/index.js +31 -3
  113. package/lib/client/index.js.map +1 -1
  114. package/lib/client/markdown/SourceImage.js +52 -0
  115. package/lib/client/markdown/SourceImage.js.map +1 -0
  116. package/lib/client/markdown/blocks.js +150 -115
  117. package/lib/client/markdown/blocks.js.map +1 -1
  118. package/lib/client/markdown/render.js +23 -5
  119. package/lib/client/markdown/render.js.map +1 -1
  120. package/lib/client/markdown/source-chip.js +2 -1
  121. package/lib/client/markdown/source-chip.js.map +1 -1
  122. package/lib/client/oidc-browser.js +39 -0
  123. package/lib/client/oidc-browser.js.map +1 -0
  124. package/lib/client/panels/PanelHost.js +23 -1
  125. package/lib/client/panels/PanelHost.js.map +1 -1
  126. package/lib/client/settings/sections/interface.js +2 -1
  127. package/lib/client/settings/sections/interface.js.map +1 -1
  128. package/lib/client/settings/sections/sources.js +1 -1
  129. package/lib/client/settings/sections/sources.js.map +1 -1
  130. package/lib/client/settings/sections/status.js +3 -1
  131. package/lib/client/settings/sections/status.js.map +1 -1
  132. package/lib/client/settings/styles.js +18 -28
  133. package/lib/client/settings/styles.js.map +1 -1
  134. package/lib/client/source-filters-styles.js +11 -0
  135. package/lib/client/source-filters-styles.js.map +1 -0
  136. package/lib/client/styles.js +56 -5
  137. package/lib/client/styles.js.map +1 -1
  138. package/lib/client/types.js.map +1 -1
  139. package/lib/client/use-right-rail.js +1 -1
  140. package/lib/client/use-right-rail.js.map +1 -1
  141. package/lib/client/user-settings/IntegrationTokensPage.js +30 -6
  142. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
  143. package/lib/client.js +540 -71128
  144. package/lib/client.js.map +1 -1
  145. package/lib/config-resolvers/accounts.js +5 -4
  146. package/lib/config-resolvers/accounts.js.map +1 -1
  147. package/lib/config-resolvers/defaults.js +20 -3
  148. package/lib/config-resolvers/defaults.js.map +1 -1
  149. package/lib/config-resolvers/oidc.js +53 -0
  150. package/lib/config-resolvers/oidc.js.map +1 -0
  151. package/lib/config-resolvers/sources.js +2 -0
  152. package/lib/config-resolvers/sources.js.map +1 -1
  153. package/lib/config.js +74 -0
  154. package/lib/config.js.map +1 -1
  155. package/lib/forms/attachments.js +214 -0
  156. package/lib/forms/attachments.js.map +1 -0
  157. package/lib/forms/errors.js +37 -0
  158. package/lib/forms/errors.js.map +1 -0
  159. package/lib/forms/fingerprint.js +21 -0
  160. package/lib/forms/fingerprint.js.map +1 -0
  161. package/lib/forms/gate.js +125 -0
  162. package/lib/forms/gate.js.map +1 -0
  163. package/lib/forms/schema.js +182 -0
  164. package/lib/forms/schema.js.map +1 -0
  165. package/lib/forms/service.js +220 -0
  166. package/lib/forms/service.js.map +1 -0
  167. package/lib/forms/store.js +194 -0
  168. package/lib/forms/store.js.map +1 -0
  169. package/lib/forms/types.js +2 -0
  170. package/lib/forms/types.js.map +1 -0
  171. package/lib/forms/validation.js +113 -0
  172. package/lib/forms/validation.js.map +1 -0
  173. package/lib/index.js +276 -5
  174. package/lib/index.js.map +1 -1
  175. package/lib/integration/host-runner.js +1 -0
  176. package/lib/integration/host-runner.js.map +1 -1
  177. package/lib/integration/question-policy.js +126 -0
  178. package/lib/integration/question-policy.js.map +1 -0
  179. package/lib/integration/service.js +2 -0
  180. package/lib/integration/service.js.map +1 -1
  181. package/lib/llm-identity.js +27 -0
  182. package/lib/llm-identity.js.map +1 -0
  183. package/lib/markdown-frontmatter.js +47 -0
  184. package/lib/markdown-frontmatter.js.map +1 -0
  185. package/lib/markdown-images.js +33 -0
  186. package/lib/markdown-images.js.map +1 -0
  187. package/lib/oidc/http.js +30 -0
  188. package/lib/oidc/http.js.map +1 -0
  189. package/lib/oidc/service.js +250 -0
  190. package/lib/oidc/service.js.map +1 -0
  191. package/lib/prompt-notes.js +1 -1
  192. package/lib/prompt-notes.js.map +1 -1
  193. package/lib/provenance/collector.js +2 -0
  194. package/lib/provenance/collector.js.map +1 -1
  195. package/lib/provenance/connectors.js +25 -19
  196. package/lib/provenance/connectors.js.map +1 -1
  197. package/lib/provenance/dedupe.js +17 -0
  198. package/lib/provenance/dedupe.js.map +1 -1
  199. package/lib/provenance/document-preview.js +12 -2
  200. package/lib/provenance/document-preview.js.map +1 -1
  201. package/lib/provenance/extractors.js +23 -5
  202. package/lib/provenance/extractors.js.map +1 -1
  203. package/lib/provenance/file-preview.js +9 -2
  204. package/lib/provenance/file-preview.js.map +1 -1
  205. package/lib/provenance/integration-extractor.js +5 -6
  206. package/lib/provenance/integration-extractor.js.map +1 -1
  207. package/lib/provenance/snapshot-store.js +2 -0
  208. package/lib/provenance/snapshot-store.js.map +1 -1
  209. package/lib/provenance/source-content.js +103 -0
  210. package/lib/provenance/source-content.js.map +1 -0
  211. package/lib/provenance/source-image.js +57 -0
  212. package/lib/provenance/source-image.js.map +1 -0
  213. package/lib/provenance/spreadsheet-preview.js +52 -0
  214. package/lib/provenance/spreadsheet-preview.js.map +1 -0
  215. package/lib/qa-tools/activation-manager.js +24 -2
  216. package/lib/qa-tools/activation-manager.js.map +1 -1
  217. package/lib/qa-tools/catalog.js +11 -1
  218. package/lib/qa-tools/catalog.js.map +1 -1
  219. package/lib/qa-tools/index.js +27 -0
  220. package/lib/qa-tools/index.js.map +1 -1
  221. package/lib/qa-tools/request-user-form.js +121 -0
  222. package/lib/qa-tools/request-user-form.js.map +1 -0
  223. package/lib/questions.js +6 -1
  224. package/lib/questions.js.map +1 -1
  225. package/lib/resolve-config.js +2 -0
  226. package/lib/resolve-config.js.map +1 -1
  227. package/lib/secure-session.js +14 -8
  228. package/lib/secure-session.js.map +1 -1
  229. package/lib/shared/documents.js +12 -0
  230. package/lib/shared/documents.js.map +1 -1
  231. package/lib/typert.host.js +5136 -1341
  232. package/lib/typert.remote-client.d.ts +141 -7
  233. package/lib/typert.remote-client.js +5896 -2255
  234. package/lib/types/account-remotes.d.ts +3 -0
  235. package/lib/types/accounts/database.d.ts +13 -0
  236. package/lib/types/accounts/file.d.ts +2 -0
  237. package/lib/types/accounts/store.d.ts +23 -1
  238. package/lib/types/accounts/token.d.ts +3 -1
  239. package/lib/types/admin/metrics.d.ts +5 -1
  240. package/lib/types/admin/read-budget.d.ts +8 -0
  241. package/lib/types/admin/service.d.ts +17 -0
  242. package/lib/types/admin/session-log.d.ts +30 -1
  243. package/lib/types/answer-review.js +2 -0
  244. package/lib/types/answer-review.js.map +1 -0
  245. package/lib/types/chat-sharing/store.d.ts +1 -0
  246. package/lib/types/chat-sharing/transport.d.ts +1 -0
  247. package/lib/types/chat-sharing/uploads.d.ts +2 -1
  248. package/lib/types/client/QaAccountsController.d.ts +5 -0
  249. package/lib/types/client/QaRouteController.d.ts +1 -0
  250. package/lib/types/client/QaSessionController.d.ts +12 -3
  251. package/lib/types/client/QaSurface.d.ts +2 -0
  252. package/lib/types/client/admin/CapabilityPicker.d.ts +14 -0
  253. package/lib/types/client/admin/CoverageNotice.d.ts +6 -0
  254. package/lib/types/client/admin/RoleEditor.d.ts +15 -0
  255. package/lib/types/client/admin/capability-selection.d.ts +27 -0
  256. package/lib/types/client/admin/shared.d.ts +39 -1
  257. package/lib/types/client/answer-review.d.ts +16 -0
  258. package/lib/types/client/components/QaAnswerReviewStatus.d.ts +8 -0
  259. package/lib/types/client/components/QaAuthGate.d.ts +2 -0
  260. package/lib/types/client/components/QaChatActions.d.ts +7 -0
  261. package/lib/types/client/components/QaChatSharing.d.ts +4 -2
  262. package/lib/types/client/components/QaFormItem.d.ts +20 -0
  263. package/lib/types/client/components/QaInputForm.d.ts +18 -0
  264. package/lib/types/client/components/QaMarkdownPreview.d.ts +13 -0
  265. package/lib/types/client/components/QaModal.d.ts +9 -0
  266. package/lib/types/client/components/QaRightRail.d.ts +3 -2
  267. package/lib/types/client/components/QaRightRailResize.d.ts +9 -0
  268. package/lib/types/client/components/QaSidebar.d.ts +2 -0
  269. package/lib/types/client/components/QaSourceFilters.d.ts +12 -0
  270. package/lib/types/client/components/QaSpreadsheetPreview.d.ts +8 -0
  271. package/lib/types/client/components/QaWelcomeNotice.d.ts +1 -1
  272. package/lib/types/client/components/QaZoomImage.d.ts +38 -0
  273. package/lib/types/client/forms-styles.d.ts +2 -0
  274. package/lib/types/client/forms.d.ts +23 -0
  275. package/lib/types/client/markdown/SourceImage.d.ts +7 -0
  276. package/lib/types/client/markdown/blocks.d.ts +8 -1
  277. package/lib/types/client/markdown/render.d.ts +5 -1
  278. package/lib/types/client/markdown/source-chip.d.ts +1 -0
  279. package/lib/types/client/oidc-browser.d.ts +12 -0
  280. package/lib/types/client/settings/styles.d.ts +2 -5
  281. package/lib/types/client/source-filters-styles.d.ts +2 -0
  282. package/lib/types/client/types.d.ts +18 -6
  283. package/lib/types/config-resolvers/oidc.d.ts +3 -0
  284. package/lib/types/forms/attachments.d.ts +48 -0
  285. package/lib/types/forms/errors.d.ts +11 -0
  286. package/lib/types/forms/fingerprint.d.ts +9 -0
  287. package/lib/types/forms/gate.d.ts +33 -0
  288. package/lib/types/forms/schema.d.ts +72 -0
  289. package/lib/types/forms/service.d.ts +15 -0
  290. package/lib/types/forms/store.d.ts +25 -0
  291. package/lib/types/forms/types.d.ts +215 -0
  292. package/lib/types/forms/validation.d.ts +20 -0
  293. package/lib/types/index.d.ts +36 -3
  294. package/lib/types/integration/contract.d.ts +1 -0
  295. package/lib/types/integration/question-policy.d.ts +20 -0
  296. package/lib/types/integration/service.d.ts +1 -0
  297. package/lib/types/llm-identity.d.ts +20 -0
  298. package/lib/types/markdown-frontmatter.d.ts +10 -0
  299. package/lib/types/markdown-images.d.ts +3 -0
  300. package/lib/types/oidc/http.d.ts +5 -0
  301. package/lib/types/oidc/service.d.ts +30 -0
  302. package/lib/types/oidc.js +2 -0
  303. package/lib/types/oidc.js.map +1 -0
  304. package/lib/types/prompt-notes.d.ts +1 -1
  305. package/lib/types/provenance/document-preview.d.ts +3 -2
  306. package/lib/types/provenance/file-preview.d.ts +2 -1
  307. package/lib/types/provenance/source-content.d.ts +19 -0
  308. package/lib/types/provenance/source-image.d.ts +4 -0
  309. package/lib/types/provenance/spreadsheet-preview.d.ts +5 -0
  310. package/lib/types/provenance/types.d.ts +3 -0
  311. package/lib/types/qa-tools/activation-manager.d.ts +5 -0
  312. package/lib/types/qa-tools/catalog.d.ts +4 -1
  313. package/lib/types/qa-tools/index.d.ts +5 -1
  314. package/lib/types/qa-tools/request-user-form.d.ts +5 -0
  315. package/lib/types/questions.d.ts +2 -1
  316. package/lib/types/secure-session.d.ts +1 -0
  317. package/lib/types/shared/documents.d.ts +2 -0
  318. package/lib/types/types/accounts.d.ts +7 -1
  319. package/lib/types/types/admin.d.ts +6 -0
  320. package/lib/types/types/answer-review.d.ts +11 -0
  321. package/lib/types/types/config.d.ts +9 -0
  322. package/lib/types/types/oidc.d.ts +36 -0
  323. package/lib/types/types/session.d.ts +18 -3
  324. package/lib/types/types.d.ts +3 -0
  325. package/package.json +58 -56
package/lib/index.js CHANGED
@@ -33,12 +33,14 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
33
33
  done = true;
34
34
  };
35
35
  import { randomUUID } from "node:crypto";
36
+ import { readSourceImage as readSourceImagePreview } from "./provenance/source-image.js";
36
37
  import path from "node:path";
37
38
  import { defaultAccountsFilePath } from "./accounts/store.js";
38
39
  import { QaChatSharingStore } from "./chat-sharing/store.js";
39
40
  import { QaChatTransport } from "./chat-sharing/transport.js";
40
41
  import { QaChatTurnGuard } from "./chat-sharing/turn-guard.js";
41
42
  import { installQaNativeFence } from "./chat-sharing/native-fence.js";
43
+ import { QaIntegrationQuestionPolicy } from "./integration/question-policy.js";
42
44
  import { qaChatPublishedFile, qaChatAttachmentPath, } from "./chat-sharing/resources.js";
43
45
  import { installQaChatUploads } from "./chat-sharing/uploads.js";
44
46
  import { forkQaSession } from "./session-fork-host.js";
@@ -56,11 +58,19 @@ import { QaApprovalGate } from "./approvals.js";
56
58
  import { QaAttestationError, qaAttestationFailureMessage, } from "./attestation.js";
57
59
  import { QaFileDeleteGate } from "./qa-tools/file-delete-gate.js";
58
60
  import { QaQuestionGate } from "./questions.js";
61
+ import { QaFormStore } from "./forms/store.js";
62
+ import { QaFormService } from "./forms/service.js";
63
+ import { QaFormGate } from "./forms/gate.js";
64
+ import { QaFormAttachmentAdapter, } from "./forms/attachments.js";
65
+ import { formFailure, QaFormError } from "./forms/errors.js";
59
66
  import { QaSessionOwnership } from "./session-ownership.js";
67
+ import { QaLlmIdentity } from "./llm-identity.js";
60
68
  import { registerTurnFailureLog } from "./turn-failure-log.js";
61
69
  import { entryRedirectRow } from "./entry-redirect.js";
62
70
  import { qaKioskDeployment } from "./ui-mode.js";
63
71
  import { registerQaNavigationRoute } from "./host-route.js";
72
+ import { QaOidcService, oidcRefusal } from "./oidc/service.js";
73
+ import { registerQaOidcRoute } from "./oidc/http.js";
64
74
  import { makeLaunchTokenSource } from "./launch-token.js";
65
75
  import { QaIntegrationPrincipalBindings } from "./integration-principals.js";
66
76
  import { registerQaIntegrationRoutes } from "./integration/http.js";
@@ -136,6 +146,9 @@ let QaSurface = (() => {
136
146
  let _instanceExtraInitializers = [];
137
147
  let _accountsRegister_decorators;
138
148
  let _accountsLogin_decorators;
149
+ let _accountsOidcStart_decorators;
150
+ let _accountsOidcComplete_decorators;
151
+ let _accountsOidcLogout_decorators;
139
152
  let _accountsChangePassword_decorators;
140
153
  let _accountsRequestPasswordReset_decorators;
141
154
  let _accountsWhoami_decorators;
@@ -148,6 +161,7 @@ let QaSurface = (() => {
148
161
  let _accountsListServiceTokens_decorators;
149
162
  let _accountsCreateServiceToken_decorators;
150
163
  let _accountsRevokeServiceToken_decorators;
164
+ let _accountsSetServiceTokenClarifications_decorators;
151
165
  let _describe_decorators;
152
166
  let _queueStatus_decorators;
153
167
  let _createSession_decorators;
@@ -215,9 +229,16 @@ let QaSurface = (() => {
215
229
  let _pendingApprovals_decorators;
216
230
  let _answerApproval_decorators;
217
231
  let _pendingQuestions_decorators;
232
+ let _listForms_decorators;
233
+ let _getForm_decorators;
234
+ let _mutateForm_decorators;
235
+ let _validateFormStep_decorators;
236
+ let _formCapabilities_decorators;
237
+ let _readFormAttachment_decorators;
218
238
  let _answerQuestion_decorators;
219
239
  let _cancelQuestion_decorators;
220
240
  let _readSourceFile_decorators;
241
+ let _readSourceImage_decorators;
221
242
  let _listWorkspaceFiles_decorators;
222
243
  let _readWorkspaceFile_decorators;
223
244
  let _readWorkspaceFileChunk_decorators;
@@ -238,6 +259,9 @@ let QaSurface = (() => {
238
259
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
239
260
  _accountsRegister_decorators = [Remote("accountsRegister")];
240
261
  _accountsLogin_decorators = [Remote("accountsLogin")];
262
+ _accountsOidcStart_decorators = [Remote("accountsOidcStart")];
263
+ _accountsOidcComplete_decorators = [Remote("accountsOidcComplete")];
264
+ _accountsOidcLogout_decorators = [Remote("accountsOidcLogout")];
241
265
  _accountsChangePassword_decorators = [Remote("accountsChangePassword")];
242
266
  _accountsRequestPasswordReset_decorators = [Remote("accountsRequestPasswordReset")];
243
267
  _accountsWhoami_decorators = [Remote("accountsWhoami")];
@@ -250,6 +274,7 @@ let QaSurface = (() => {
250
274
  _accountsListServiceTokens_decorators = [Remote("accountsListServiceTokens")];
251
275
  _accountsCreateServiceToken_decorators = [Remote("accountsCreateServiceToken")];
252
276
  _accountsRevokeServiceToken_decorators = [Remote("accountsRevokeServiceToken")];
277
+ _accountsSetServiceTokenClarifications_decorators = [Remote("accountsSetServiceTokenClarifications")];
253
278
  _describe_decorators = [Remote("describe")];
254
279
  _queueStatus_decorators = [Remote("queueStatus")];
255
280
  _createSession_decorators = [Remote("createSession")];
@@ -317,9 +342,16 @@ let QaSurface = (() => {
317
342
  _pendingApprovals_decorators = [Remote("pendingApprovals")];
318
343
  _answerApproval_decorators = [Remote("answerApproval")];
319
344
  _pendingQuestions_decorators = [Remote("pendingQuestions")];
345
+ _listForms_decorators = [Remote("listForms")];
346
+ _getForm_decorators = [Remote("getForm")];
347
+ _mutateForm_decorators = [Remote("mutateForm")];
348
+ _validateFormStep_decorators = [Remote("validateFormStep")];
349
+ _formCapabilities_decorators = [Remote("formCapabilities")];
350
+ _readFormAttachment_decorators = [Remote("readFormAttachment")];
320
351
  _answerQuestion_decorators = [Remote("answerQuestion")];
321
352
  _cancelQuestion_decorators = [Remote("cancelQuestion")];
322
353
  _readSourceFile_decorators = [Remote("readSourceFile")];
354
+ _readSourceImage_decorators = [Remote("readSourceImage")];
323
355
  _listWorkspaceFiles_decorators = [Remote("listWorkspaceFiles")];
324
356
  _readWorkspaceFile_decorators = [Remote("readWorkspaceFile")];
325
357
  _readWorkspaceFileChunk_decorators = [Remote("readWorkspaceFileChunk")];
@@ -337,6 +369,9 @@ let QaSurface = (() => {
337
369
  _slashExecute_decorators = [Remote("slashExecute")];
338
370
  __esDecorate(this, null, _accountsRegister_decorators, { kind: "method", name: "accountsRegister", static: false, private: false, access: { has: obj => "accountsRegister" in obj, get: obj => obj.accountsRegister }, metadata: _metadata }, null, _instanceExtraInitializers);
339
371
  __esDecorate(this, null, _accountsLogin_decorators, { kind: "method", name: "accountsLogin", static: false, private: false, access: { has: obj => "accountsLogin" in obj, get: obj => obj.accountsLogin }, metadata: _metadata }, null, _instanceExtraInitializers);
372
+ __esDecorate(this, null, _accountsOidcStart_decorators, { kind: "method", name: "accountsOidcStart", static: false, private: false, access: { has: obj => "accountsOidcStart" in obj, get: obj => obj.accountsOidcStart }, metadata: _metadata }, null, _instanceExtraInitializers);
373
+ __esDecorate(this, null, _accountsOidcComplete_decorators, { kind: "method", name: "accountsOidcComplete", static: false, private: false, access: { has: obj => "accountsOidcComplete" in obj, get: obj => obj.accountsOidcComplete }, metadata: _metadata }, null, _instanceExtraInitializers);
374
+ __esDecorate(this, null, _accountsOidcLogout_decorators, { kind: "method", name: "accountsOidcLogout", static: false, private: false, access: { has: obj => "accountsOidcLogout" in obj, get: obj => obj.accountsOidcLogout }, metadata: _metadata }, null, _instanceExtraInitializers);
340
375
  __esDecorate(this, null, _accountsChangePassword_decorators, { kind: "method", name: "accountsChangePassword", static: false, private: false, access: { has: obj => "accountsChangePassword" in obj, get: obj => obj.accountsChangePassword }, metadata: _metadata }, null, _instanceExtraInitializers);
341
376
  __esDecorate(this, null, _accountsRequestPasswordReset_decorators, { kind: "method", name: "accountsRequestPasswordReset", static: false, private: false, access: { has: obj => "accountsRequestPasswordReset" in obj, get: obj => obj.accountsRequestPasswordReset }, metadata: _metadata }, null, _instanceExtraInitializers);
342
377
  __esDecorate(this, null, _accountsWhoami_decorators, { kind: "method", name: "accountsWhoami", static: false, private: false, access: { has: obj => "accountsWhoami" in obj, get: obj => obj.accountsWhoami }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -349,6 +384,7 @@ let QaSurface = (() => {
349
384
  __esDecorate(this, null, _accountsListServiceTokens_decorators, { kind: "method", name: "accountsListServiceTokens", static: false, private: false, access: { has: obj => "accountsListServiceTokens" in obj, get: obj => obj.accountsListServiceTokens }, metadata: _metadata }, null, _instanceExtraInitializers);
350
385
  __esDecorate(this, null, _accountsCreateServiceToken_decorators, { kind: "method", name: "accountsCreateServiceToken", static: false, private: false, access: { has: obj => "accountsCreateServiceToken" in obj, get: obj => obj.accountsCreateServiceToken }, metadata: _metadata }, null, _instanceExtraInitializers);
351
386
  __esDecorate(this, null, _accountsRevokeServiceToken_decorators, { kind: "method", name: "accountsRevokeServiceToken", static: false, private: false, access: { has: obj => "accountsRevokeServiceToken" in obj, get: obj => obj.accountsRevokeServiceToken }, metadata: _metadata }, null, _instanceExtraInitializers);
387
+ __esDecorate(this, null, _accountsSetServiceTokenClarifications_decorators, { kind: "method", name: "accountsSetServiceTokenClarifications", static: false, private: false, access: { has: obj => "accountsSetServiceTokenClarifications" in obj, get: obj => obj.accountsSetServiceTokenClarifications }, metadata: _metadata }, null, _instanceExtraInitializers);
352
388
  __esDecorate(this, null, _describe_decorators, { kind: "method", name: "describe", static: false, private: false, access: { has: obj => "describe" in obj, get: obj => obj.describe }, metadata: _metadata }, null, _instanceExtraInitializers);
353
389
  __esDecorate(this, null, _queueStatus_decorators, { kind: "method", name: "queueStatus", static: false, private: false, access: { has: obj => "queueStatus" in obj, get: obj => obj.queueStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
354
390
  __esDecorate(this, null, _createSession_decorators, { kind: "method", name: "createSession", static: false, private: false, access: { has: obj => "createSession" in obj, get: obj => obj.createSession }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -416,9 +452,16 @@ let QaSurface = (() => {
416
452
  __esDecorate(this, null, _pendingApprovals_decorators, { kind: "method", name: "pendingApprovals", static: false, private: false, access: { has: obj => "pendingApprovals" in obj, get: obj => obj.pendingApprovals }, metadata: _metadata }, null, _instanceExtraInitializers);
417
453
  __esDecorate(this, null, _answerApproval_decorators, { kind: "method", name: "answerApproval", static: false, private: false, access: { has: obj => "answerApproval" in obj, get: obj => obj.answerApproval }, metadata: _metadata }, null, _instanceExtraInitializers);
418
454
  __esDecorate(this, null, _pendingQuestions_decorators, { kind: "method", name: "pendingQuestions", static: false, private: false, access: { has: obj => "pendingQuestions" in obj, get: obj => obj.pendingQuestions }, metadata: _metadata }, null, _instanceExtraInitializers);
455
+ __esDecorate(this, null, _listForms_decorators, { kind: "method", name: "listForms", static: false, private: false, access: { has: obj => "listForms" in obj, get: obj => obj.listForms }, metadata: _metadata }, null, _instanceExtraInitializers);
456
+ __esDecorate(this, null, _getForm_decorators, { kind: "method", name: "getForm", static: false, private: false, access: { has: obj => "getForm" in obj, get: obj => obj.getForm }, metadata: _metadata }, null, _instanceExtraInitializers);
457
+ __esDecorate(this, null, _mutateForm_decorators, { kind: "method", name: "mutateForm", static: false, private: false, access: { has: obj => "mutateForm" in obj, get: obj => obj.mutateForm }, metadata: _metadata }, null, _instanceExtraInitializers);
458
+ __esDecorate(this, null, _validateFormStep_decorators, { kind: "method", name: "validateFormStep", static: false, private: false, access: { has: obj => "validateFormStep" in obj, get: obj => obj.validateFormStep }, metadata: _metadata }, null, _instanceExtraInitializers);
459
+ __esDecorate(this, null, _formCapabilities_decorators, { kind: "method", name: "formCapabilities", static: false, private: false, access: { has: obj => "formCapabilities" in obj, get: obj => obj.formCapabilities }, metadata: _metadata }, null, _instanceExtraInitializers);
460
+ __esDecorate(this, null, _readFormAttachment_decorators, { kind: "method", name: "readFormAttachment", static: false, private: false, access: { has: obj => "readFormAttachment" in obj, get: obj => obj.readFormAttachment }, metadata: _metadata }, null, _instanceExtraInitializers);
419
461
  __esDecorate(this, null, _answerQuestion_decorators, { kind: "method", name: "answerQuestion", static: false, private: false, access: { has: obj => "answerQuestion" in obj, get: obj => obj.answerQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
420
462
  __esDecorate(this, null, _cancelQuestion_decorators, { kind: "method", name: "cancelQuestion", static: false, private: false, access: { has: obj => "cancelQuestion" in obj, get: obj => obj.cancelQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
421
463
  __esDecorate(this, null, _readSourceFile_decorators, { kind: "method", name: "readSourceFile", static: false, private: false, access: { has: obj => "readSourceFile" in obj, get: obj => obj.readSourceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
464
+ __esDecorate(this, null, _readSourceImage_decorators, { kind: "method", name: "readSourceImage", static: false, private: false, access: { has: obj => "readSourceImage" in obj, get: obj => obj.readSourceImage }, metadata: _metadata }, null, _instanceExtraInitializers);
422
465
  __esDecorate(this, null, _listWorkspaceFiles_decorators, { kind: "method", name: "listWorkspaceFiles", static: false, private: false, access: { has: obj => "listWorkspaceFiles" in obj, get: obj => obj.listWorkspaceFiles }, metadata: _metadata }, null, _instanceExtraInitializers);
423
466
  __esDecorate(this, null, _readWorkspaceFile_decorators, { kind: "method", name: "readWorkspaceFile", static: false, private: false, access: { has: obj => "readWorkspaceFile" in obj, get: obj => obj.readWorkspaceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
424
467
  __esDecorate(this, null, _readWorkspaceFileChunk_decorators, { kind: "method", name: "readWorkspaceFileChunk", static: false, private: false, access: { has: obj => "readWorkspaceFileChunk" in obj, get: obj => obj.readWorkspaceFileChunk }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -444,6 +487,13 @@ let QaSurface = (() => {
444
487
  approvals;
445
488
  fileDeleteGate;
446
489
  userQuestions;
490
+ formService;
491
+ formGate;
492
+ formAttachments;
493
+ forms() {
494
+ return (this.formService ??= new QaFormService(new QaFormStore(path.join(path.dirname(defaultAccountsFilePath()), "qa-forms.db")), () => this.getConfig().forms, (session) => this.accountRemotes.resolve(this.getConfig())?.ownerIdOf(session) ??
495
+ session));
496
+ }
447
497
  provenance;
448
498
  notes;
449
499
  /** Assigned after the admission gate; that gate only reads it per execution. */
@@ -472,6 +522,12 @@ let QaSurface = (() => {
472
522
  integrationPrincipals = new QaIntegrationPrincipalBindings();
473
523
  webServer;
474
524
  disposeRoute;
525
+ oidc = new QaOidcService({
526
+ config: () => this.getConfig(),
527
+ accounts: () => this.accountRemotes.resolve(this.getConfig()),
528
+ });
529
+ disposeOidcRoute;
530
+ oidcRouteKey;
475
531
  routeKey;
476
532
  /**
477
533
  * The HTTP API an external application asks questions through. Constructed
@@ -509,6 +565,7 @@ let QaSurface = (() => {
509
565
  pluginId: "dsh-qa-surface",
510
566
  consoleSink: createHostLoggerSink(ctx.logger),
511
567
  });
568
+ this.formAttachments = new QaFormAttachmentAdapter(() => this.forms(), () => ctx.get("attachments"));
512
569
  this.accountRemotes = createQaAccountRemotes({
513
570
  getConfig: () => this.getConfig(),
514
571
  logger: this.logger,
@@ -623,7 +680,7 @@ let QaSurface = (() => {
623
680
  }, "dsh-qa-surface.chat-sharing");
624
681
  ctx.inject(["typertGateway", "connection"], () => {
625
682
  const dispose = installQaNativeFence(ctx, () => this.getConfig().accounts.enabled);
626
- const disposeUploads = installQaChatUploads(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id));
683
+ const disposeUploads = installQaChatUploads(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id), this.formAttachments);
627
684
  return async () => {
628
685
  dispose();
629
686
  await disposeUploads();
@@ -654,8 +711,28 @@ let QaSurface = (() => {
654
711
  // operator's answer while they are interactive. The question seam shares
655
712
  // the ownership map: one chat, one surface answering it.
656
713
  const ownership = new QaSessionOwnership((sessionId) => this.admission.knowsSession(sessionId));
714
+ ownership.install(ctx);
715
+ new QaLlmIdentity(ctx, {
716
+ rootOf: (sessionId) => ownership.rootOf(sessionId),
717
+ accounts: () => this.accountRemotes.resolve(this.getConfig()),
718
+ });
657
719
  this.approvals = new QaApprovalGate(ctx, () => this.getConfig().interaction.approvals === "interactive", ownership, this.logger);
658
- this.userQuestions = new QaQuestionGate(ctx, () => this.getConfig().interaction.questions === "interactive", ownership, this.logger);
720
+ const integrationQuestionPolicy = new QaIntegrationQuestionPolicy(ctx, () => this.accountRemotes.resolve(this.getConfig()), (id) => ownership.rootOf(id));
721
+ ctx.effect(() => () => integrationQuestionPolicy.dispose(), "qa-surface: integration question policy");
722
+ this.userQuestions = new QaQuestionGate(ctx, () => this.getConfig().interaction.questions === "interactive", ownership, this.logger, (agent) => integrationQuestionPolicy.allowed(agent) &&
723
+ !this.formGate?.hasSession(ownership.rootOf(String(agent.session.id)) ?? ""));
724
+ this.formGate = new QaFormGate(() => this.forms(), (id) => ownership.rootOf(id), (id) => this.userQuestions.list(id).length > 0 ||
725
+ this.approvals.list(id).length > 0, (exec) => this.getConfig().forms.enabled &&
726
+ exec.agent !== undefined &&
727
+ integrationQuestionPolicy.allowed(exec.agent) &&
728
+ this.admission.knowsSession(String(exec.agent.session.id)), () => this.getConfig().accounts.enabled &&
729
+ this.ctx.get("fileUploads") !== undefined &&
730
+ this.formAttachments.available());
731
+ this.formGate.install(ctx);
732
+ ctx.effect(() => () => {
733
+ this.formGate.dispose();
734
+ this.formService?.store.close();
735
+ }, "dsh-qa-surface.forms");
659
736
  // The destructive tool of the QA catalog composes the same approval flow
660
737
  // around itself: registered without `prepend`, it sits inside the approval
661
738
  // gate and answers `ask` for every file_delete call of an attested chat,
@@ -706,6 +783,9 @@ let QaSurface = (() => {
706
783
  // The QA tool catalog is attached per agent, never at boot: nothing here
707
784
  // reaches the model until a managed agent loads the activation skill.
708
785
  this.tools = new QaTools(ctx, {
786
+ forms: this.formGate,
787
+ formsEnabled: () => this.getConfig().forms.enabled,
788
+ formProjection: (submission) => this.formAttachments.readable(submission),
709
789
  logger: this.logger,
710
790
  dynamicActivation: this.getConfig().tools.dynamicActivation,
711
791
  activationSkill: this.getConfig().tools.activationSkill,
@@ -718,6 +798,12 @@ let QaSurface = (() => {
718
798
  docsDefaultVersion: () => docsDefaultVersionOf(this.getConfig().tools),
719
799
  });
720
800
  ctx.effect(() => () => this.tools.dispose(), "dsh-qa-surface.qa-tools");
801
+ const listenVolatile = ctx.on.bind(ctx);
802
+ ctx.effect(() => listenVolatile("loader/volatile-update", () => {
803
+ this.tools.refreshForms();
804
+ if (!this.getConfig().forms.enabled)
805
+ this.formGate.cancelAll();
806
+ }), "dsh-qa-surface.form-policy");
721
807
  // The root index gains one head script: non-loopback hostnames continue
722
808
  // into /qa, the loopback operator keeps the full harness UI. Not in the
723
809
  // kiosk composition: there the index itself is served under /qa, so the
@@ -744,6 +830,7 @@ let QaSurface = (() => {
744
830
  const config = this.getConfig();
745
831
  this.refreshRoute();
746
832
  this.refreshIntegrationRoutes();
833
+ this.refreshOidcRoute();
747
834
  this.warnDocumentsMoved();
748
835
  this.warnLegacySlashDefaults();
749
836
  this.logger.info("config.updated", {
@@ -756,11 +843,16 @@ let QaSurface = (() => {
756
843
  this.webServer = webContext.webServer;
757
844
  this.refreshRoute();
758
845
  this.refreshIntegrationRoutes();
846
+ this.refreshOidcRoute();
759
847
  webContext.effect(() => () => {
760
848
  this.disposeRoute?.();
761
849
  this.disposeRoute = undefined;
762
850
  this.routeKey = undefined;
763
851
  this.disposeIntegrationRoutes?.();
852
+ this.disposeOidcRoute?.();
853
+ this.disposeOidcRoute = undefined;
854
+ this.oidcRouteKey = undefined;
855
+ this.oidc.clear();
764
856
  this.disposeIntegrationRoutes = undefined;
765
857
  this.integrationRouteKey = undefined;
766
858
  this.webServer = undefined;
@@ -811,6 +903,10 @@ let QaSurface = (() => {
811
903
  * cannot be opened must not fail the page that triggered it.
812
904
  */
813
905
  dropVanishedChats(sessionIds) {
906
+ for (const id of sessionIds) {
907
+ this.formGate?.cancel(id);
908
+ this.formService?.store.cancelSession(id);
909
+ }
814
910
  try {
815
911
  const rows = this.quality().dropConversations(sessionIds);
816
912
  this.logger.info("quality.vanished-conversations-dropped", {
@@ -911,6 +1007,17 @@ let QaSurface = (() => {
911
1007
  accountsLogin(email, password) {
912
1008
  return this.accountRemotes.login(email, password);
913
1009
  }
1010
+ accountsOidcStart() {
1011
+ if (!this.disposeOidcRoute)
1012
+ return Promise.reject(oidcRefusal());
1013
+ return this.oidc.start();
1014
+ }
1015
+ accountsOidcComplete(handoff, completionKey) {
1016
+ return this.oidc.complete(handoff, completionKey);
1017
+ }
1018
+ accountsOidcLogout(token) {
1019
+ return this.oidc.logout(token);
1020
+ }
914
1021
  /** Identity probe; safe to call with an empty or expired token. */
915
1022
  accountsChangePassword(token, currentPassword, nextPassword) {
916
1023
  return this.accountRemotes.changePassword(token, currentPassword, nextPassword);
@@ -998,6 +1105,9 @@ let QaSurface = (() => {
998
1105
  accountsRevokeServiceToken(token, tokenId) {
999
1106
  return this.accountRemotes.revokeServiceToken(token, tokenId);
1000
1107
  }
1108
+ accountsSetServiceTokenClarifications(token, tokenId, allowed) {
1109
+ return this.accountRemotes.setServiceTokenClarifications(token, tokenId, allowed);
1110
+ }
1001
1111
  /**
1002
1112
  * Serve the effective QA configuration to the browser. The DSH gateway pins
1003
1113
  * settings RPCs to loopback, so a browser served over the LAN always sees
@@ -1387,7 +1497,9 @@ let QaSurface = (() => {
1387
1497
  }
1388
1498
  async chatAudit(token, sessionId, full) {
1389
1499
  this.requireChatOwner(token, sessionId);
1390
- await this.secureSession(token, sessionId);
1500
+ // Sidebar summaries read stored audit metadata; they do not need an agent.
1501
+ if (full)
1502
+ await this.secureSession(token, sessionId);
1391
1503
  this.requireChatOwner(token, sessionId);
1392
1504
  const audit = this.ctx.get("sessionAudit");
1393
1505
  if (audit === undefined)
@@ -1504,6 +1616,115 @@ let QaSurface = (() => {
1504
1616
  return [];
1505
1617
  return this.userQuestions.list(sessionId);
1506
1618
  }
1619
+ /** Forms stay owner-scoped; UUIDs and a browser-supplied session never grant access. */
1620
+ async admitForm(token, sessionId) {
1621
+ try {
1622
+ this.requireChatOwner(token, sessionId);
1623
+ await this.secureSession(token, sessionId);
1624
+ this.requireChatOwner(token, sessionId);
1625
+ }
1626
+ catch {
1627
+ throw new QaFormError("ACCESS_DENIED", "Form access is unavailable.");
1628
+ }
1629
+ }
1630
+ async listForms(token, sessionId) {
1631
+ try {
1632
+ await this.admitForm(token, sessionId);
1633
+ if (!this.getConfig().forms.enabled)
1634
+ return { ok: true, value: [] };
1635
+ this.formGate.touch(sessionId);
1636
+ const service = this.forms();
1637
+ return {
1638
+ ok: true,
1639
+ value: service.store
1640
+ .list(sessionId)
1641
+ .map((r) => service.view(r, this.formGate.waiting(r.id))),
1642
+ };
1643
+ }
1644
+ catch (error) {
1645
+ return formFailure(error);
1646
+ }
1647
+ }
1648
+ async getForm(token, sessionId, formId) {
1649
+ try {
1650
+ await this.admitForm(token, sessionId);
1651
+ const s = this.forms();
1652
+ return {
1653
+ ok: true,
1654
+ value: s.view(s.get(sessionId, formId), this.formGate.waiting(formId)),
1655
+ };
1656
+ }
1657
+ catch (error) {
1658
+ return formFailure(error);
1659
+ }
1660
+ }
1661
+ async mutateForm(token, sessionId, command) {
1662
+ try {
1663
+ await this.admitForm(token, sessionId);
1664
+ const s = this.forms(), r = s.command(sessionId, command);
1665
+ this.logger.info("form.mutated", {
1666
+ sessionId,
1667
+ formId: r.id,
1668
+ action: command.action,
1669
+ revision: r.revision,
1670
+ status: r.status,
1671
+ });
1672
+ this.formGate.notify(r, command.action === "pause");
1673
+ return { ok: true, value: s.view(r, this.formGate.waiting(r.id)) };
1674
+ }
1675
+ catch (error) {
1676
+ return formFailure(error);
1677
+ }
1678
+ }
1679
+ async validateFormStep(token, sessionId, formId, stepId, revision) {
1680
+ try {
1681
+ await this.admitForm(token, sessionId);
1682
+ this.forms().step(sessionId, formId, stepId, revision);
1683
+ return { ok: true, value: null };
1684
+ }
1685
+ catch (error) {
1686
+ return formFailure(error);
1687
+ }
1688
+ }
1689
+ async formCapabilities() {
1690
+ return {
1691
+ enabled: this.getConfig().forms.enabled,
1692
+ schemaVersion: 1,
1693
+ upload: this.getConfig().accounts.enabled &&
1694
+ this.ctx.get("fileUploads") !== undefined &&
1695
+ this.formAttachments.available(),
1696
+ };
1697
+ }
1698
+ async readFormAttachment(token, sessionId, formId, resourceId) {
1699
+ try {
1700
+ await this.admitForm(token, sessionId);
1701
+ const s = this.forms(), r = s.get(sessionId, formId);
1702
+ const file = Object.values(r.attachments)
1703
+ .flat()
1704
+ .find((f) => f.resource_id === resourceId);
1705
+ if (!file)
1706
+ return {
1707
+ ok: false,
1708
+ error: {
1709
+ code: "ACCESS_DENIED",
1710
+ message: "File access is unavailable.",
1711
+ },
1712
+ };
1713
+ const data = s.store.resource(formId, resourceId);
1714
+ this.requireChatOwner(token, sessionId);
1715
+ return {
1716
+ ok: true,
1717
+ value: {
1718
+ name: file.name,
1719
+ media_type: file.media_type,
1720
+ data: Buffer.from(data).toString("base64"),
1721
+ },
1722
+ };
1723
+ }
1724
+ catch (error) {
1725
+ return formFailure(error);
1726
+ }
1727
+ }
1507
1728
  /**
1508
1729
  * Apply the operator's answers to one parked question request. Every question
1509
1730
  * of the request must be present in `answers`; one the browser omits reads as
@@ -1531,7 +1752,7 @@ let QaSurface = (() => {
1531
1752
  * read — the normal case for a deployment whose docs and code live beside
1532
1753
  * the per-account scratch directory — could never be opened in the panel.
1533
1754
  */
1534
- async readSourceFile(token, sessionId, sourcePath) {
1755
+ async readSourceFile(token, sessionId, sourcePath, selection) {
1535
1756
  const finish = await this.admitChatRead(token, sessionId, sourcePath);
1536
1757
  const config = this.getConfig();
1537
1758
  if (!config.sources.filePreview.enabled) {
@@ -1551,6 +1772,7 @@ let QaSurface = (() => {
1551
1772
  ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1552
1773
  maxBytes: config.sources.filePreview.maxBytes,
1553
1774
  maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1775
+ renderFrontmatter: config.sources.filePreview.renderFrontmatter,
1554
1776
  }).catch(async (error) => {
1555
1777
  // Only a format refusal follows successful evidence and root checks.
1556
1778
  if (!(error instanceof QaSourcePreviewError) ||
@@ -1564,6 +1786,7 @@ let QaSurface = (() => {
1564
1786
  ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1565
1787
  documents: () => this.ctx.get("documents"),
1566
1788
  maxBytes: config.sources.filePreview.maxBytes,
1789
+ ...(selection === undefined ? {} : { selection }),
1567
1790
  });
1568
1791
  return {
1569
1792
  path: sourcePath,
@@ -1586,6 +1809,31 @@ let QaSurface = (() => {
1586
1809
  throw sourcePreviewRefusal(error instanceof QaSourcePreviewError ? error.reason : "unavailable");
1587
1810
  }
1588
1811
  }
1812
+ /** Load one relative raster illustration of an attested Markdown source. */
1813
+ async readSourceImage(token, sessionId, sourcePath, imagePath) {
1814
+ const finish = await this.admitChatRead(token, sessionId, sourcePath);
1815
+ const config = this.getConfig();
1816
+ const cwd = this.ctx.agents.get(SessionId(sessionId))?.session.header.cwd;
1817
+ if (!config.sources.filePreview.enabled || cwd === undefined)
1818
+ throw sourcePreviewRefusal("unavailable");
1819
+ const attachmentRoot = this.admission.attachmentRoot();
1820
+ try {
1821
+ const result = await readSourceImagePreview({
1822
+ sourcePath,
1823
+ cwd,
1824
+ isEvidence: (canonicalPath) => this.provenance.sourceAllowed(sessionId, canonicalPath),
1825
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1826
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1827
+ maxBytes: config.sources.filePreview.maxBytes,
1828
+ maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1829
+ }, imagePath);
1830
+ finish();
1831
+ return result;
1832
+ }
1833
+ catch (error) {
1834
+ throw sourcePreviewRefusal(error instanceof QaSourcePreviewError ? error.reason : "unavailable");
1835
+ }
1836
+ }
1589
1837
  /**
1590
1838
  * List one directory of the chat's own workspace for the files panel.
1591
1839
  *
@@ -1711,7 +1959,7 @@ let QaSurface = (() => {
1711
1959
  * produced PDF is read back here and travels as base64, so the audience never
1712
1960
  * reaches an unfenced byte route.
1713
1961
  */
1714
- async previewWorkspaceDocument(token, sessionId, path) {
1962
+ async previewWorkspaceDocument(token, sessionId, path, selection) {
1715
1963
  const finish = await this.admitChatRead(token, sessionId, path);
1716
1964
  const { config, cwd } = await this.browseContext(sessionId);
1717
1965
  const attachmentRoot = this.admission.attachmentRoot();
@@ -1724,6 +1972,7 @@ let QaSurface = (() => {
1724
1972
  documents: () => this.ctx.get("documents"),
1725
1973
  sessionId,
1726
1974
  maxBytes: config.sources.filePreview.maxBytes,
1975
+ ...(selection === undefined ? {} : { selection }),
1727
1976
  });
1728
1977
  finish();
1729
1978
  return value;
@@ -1854,6 +2103,28 @@ let QaSurface = (() => {
1854
2103
  });
1855
2104
  }
1856
2105
  }
2106
+ refreshOidcRoute() {
2107
+ const config = this.getConfig();
2108
+ const key = config.enabled && config.accounts.enabled && config.accounts.oidc.enabled
2109
+ ? JSON.stringify([config.accounts.oidc, config.route.path])
2110
+ : undefined;
2111
+ if (key === this.oidcRouteKey)
2112
+ return;
2113
+ this.disposeOidcRoute?.();
2114
+ this.disposeOidcRoute = undefined;
2115
+ this.oidcRouteKey = undefined;
2116
+ this.oidc.clear();
2117
+ if (!key || !this.webServer)
2118
+ return;
2119
+ try {
2120
+ this.disposeOidcRoute = registerQaOidcRoute(this.webServer, config, this.oidc);
2121
+ this.oidcRouteKey = key;
2122
+ this.logger.info("oidc.route-registered", {});
2123
+ }
2124
+ catch {
2125
+ this.logger.error("oidc.route-unavailable", {});
2126
+ }
2127
+ }
1857
2128
  refreshRoute() {
1858
2129
  const config = this.getConfig();
1859
2130
  // Kiosk: the harness route policy owns the QA paths and serves the