arc-1 1.6.0 → 1.8.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 (411) hide show
  1. package/README.md +26 -18
  2. package/dist/adt/application-log.d.ts +36 -0
  3. package/dist/adt/application-log.d.ts.map +1 -0
  4. package/dist/adt/application-log.js +143 -0
  5. package/dist/adt/application-log.js.map +1 -0
  6. package/dist/adt/aunit-package.d.ts.map +1 -1
  7. package/dist/adt/aunit-package.js +9 -1
  8. package/dist/adt/aunit-package.js.map +1 -1
  9. package/dist/adt/ci-quality.d.ts.map +1 -1
  10. package/dist/adt/ci-quality.js +1 -1
  11. package/dist/adt/ci-quality.js.map +1 -1
  12. package/dist/adt/class-structure.d.ts +2 -1
  13. package/dist/adt/class-structure.d.ts.map +1 -1
  14. package/dist/adt/class-structure.js +28 -10
  15. package/dist/adt/class-structure.js.map +1 -1
  16. package/dist/adt/client.d.ts +27 -9
  17. package/dist/adt/client.d.ts.map +1 -1
  18. package/dist/adt/client.js +23 -16
  19. package/dist/adt/client.js.map +1 -1
  20. package/dist/adt/codeintel.d.ts +9 -23
  21. package/dist/adt/codeintel.d.ts.map +1 -1
  22. package/dist/adt/codeintel.js +14 -34
  23. package/dist/adt/codeintel.js.map +1 -1
  24. package/dist/adt/crud.d.ts +3 -2
  25. package/dist/adt/crud.d.ts.map +1 -1
  26. package/dist/adt/crud.js +13 -3
  27. package/dist/adt/crud.js.map +1 -1
  28. package/dist/adt/devtools.d.ts +21 -7
  29. package/dist/adt/devtools.d.ts.map +1 -1
  30. package/dist/adt/devtools.js +98 -44
  31. package/dist/adt/devtools.js.map +1 -1
  32. package/dist/adt/diagnostics.d.ts +2 -0
  33. package/dist/adt/diagnostics.d.ts.map +1 -1
  34. package/dist/adt/diagnostics.js +12 -10
  35. package/dist/adt/diagnostics.js.map +1 -1
  36. package/dist/adt/errors.d.ts +5 -1
  37. package/dist/adt/errors.d.ts.map +1 -1
  38. package/dist/adt/errors.js +26 -0
  39. package/dist/adt/errors.js.map +1 -1
  40. package/dist/adt/feed-schema.d.ts +32 -0
  41. package/dist/adt/feed-schema.d.ts.map +1 -0
  42. package/dist/adt/feed-schema.js +123 -0
  43. package/dist/adt/feed-schema.js.map +1 -0
  44. package/dist/adt/fm-parameter-docs.d.ts +7 -0
  45. package/dist/adt/fm-parameter-docs.d.ts.map +1 -0
  46. package/dist/adt/fm-parameter-docs.js +134 -0
  47. package/dist/adt/fm-parameter-docs.js.map +1 -0
  48. package/dist/adt/fm-signature.d.ts +8 -1
  49. package/dist/adt/fm-signature.d.ts.map +1 -1
  50. package/dist/adt/fm-signature.js +37 -28
  51. package/dist/adt/fm-signature.js.map +1 -1
  52. package/dist/adt/http-deadline.d.ts +2 -0
  53. package/dist/adt/http-deadline.d.ts.map +1 -1
  54. package/dist/adt/http-deadline.js +4 -1
  55. package/dist/adt/http-deadline.js.map +1 -1
  56. package/dist/adt/http-retry-after.d.ts +20 -0
  57. package/dist/adt/http-retry-after.d.ts.map +1 -0
  58. package/dist/adt/http-retry-after.js +37 -0
  59. package/dist/adt/http-retry-after.js.map +1 -0
  60. package/dist/adt/http.d.ts +11 -20
  61. package/dist/adt/http.d.ts.map +1 -1
  62. package/dist/adt/http.js +104 -90
  63. package/dist/adt/http.js.map +1 -1
  64. package/dist/adt/include-expansion.d.ts +143 -0
  65. package/dist/adt/include-expansion.d.ts.map +1 -0
  66. package/dist/adt/include-expansion.js +475 -0
  67. package/dist/adt/include-expansion.js.map +1 -0
  68. package/dist/adt/internal-data-operations.d.ts +3 -3
  69. package/dist/adt/internal-data-operations.d.ts.map +1 -1
  70. package/dist/adt/internal-data-operations.js +9 -2
  71. package/dist/adt/internal-data-operations.js.map +1 -1
  72. package/dist/adt/package-browser.d.ts +23 -0
  73. package/dist/adt/package-browser.d.ts.map +1 -0
  74. package/dist/adt/package-browser.js +139 -0
  75. package/dist/adt/package-browser.js.map +1 -0
  76. package/dist/adt/package-contents.d.ts +2 -0
  77. package/dist/adt/package-contents.d.ts.map +1 -1
  78. package/dist/adt/package-contents.js +3 -1
  79. package/dist/adt/package-contents.js.map +1 -1
  80. package/dist/adt/pinned-write-policy.d.ts +15 -0
  81. package/dist/adt/pinned-write-policy.d.ts.map +1 -0
  82. package/dist/adt/pinned-write-policy.js +111 -0
  83. package/dist/adt/pinned-write-policy.js.map +1 -0
  84. package/dist/adt/revision-feed.d.ts +8 -0
  85. package/dist/adt/revision-feed.d.ts.map +1 -0
  86. package/dist/adt/revision-feed.js +108 -0
  87. package/dist/adt/revision-feed.js.map +1 -0
  88. package/dist/adt/safety.d.ts +11 -0
  89. package/dist/adt/safety.d.ts.map +1 -1
  90. package/dist/adt/safety.js +18 -2
  91. package/dist/adt/safety.js.map +1 -1
  92. package/dist/adt/security-session-gate.d.ts +23 -0
  93. package/dist/adt/security-session-gate.d.ts.map +1 -0
  94. package/dist/adt/security-session-gate.js +56 -0
  95. package/dist/adt/security-session-gate.js.map +1 -0
  96. package/dist/adt/source-diff.d.ts +4 -1
  97. package/dist/adt/source-diff.d.ts.map +1 -1
  98. package/dist/adt/source-diff.js +5 -3
  99. package/dist/adt/source-diff.js.map +1 -1
  100. package/dist/adt/stored-text/chunks.d.ts +8 -0
  101. package/dist/adt/stored-text/chunks.d.ts.map +1 -0
  102. package/dist/adt/stored-text/chunks.js +55 -0
  103. package/dist/adt/stored-text/chunks.js.map +1 -0
  104. package/dist/adt/stored-text/decoder.d.ts +31 -0
  105. package/dist/adt/stored-text/decoder.d.ts.map +1 -0
  106. package/dist/adt/stored-text/decoder.js +319 -0
  107. package/dist/adt/stored-text/decoder.js.map +1 -0
  108. package/dist/adt/stored-text/errors.d.ts +10 -0
  109. package/dist/adt/stored-text/errors.d.ts.map +1 -0
  110. package/dist/adt/stored-text/errors.js +10 -0
  111. package/dist/adt/stored-text/errors.js.map +1 -0
  112. package/dist/adt/stored-text/index.d.ts +7 -0
  113. package/dist/adt/stored-text/index.d.ts.map +1 -0
  114. package/dist/adt/stored-text/index.js +6 -0
  115. package/dist/adt/stored-text/index.js.map +1 -0
  116. package/dist/adt/stored-text/key.d.ts +3 -0
  117. package/dist/adt/stored-text/key.d.ts.map +1 -0
  118. package/dist/adt/stored-text/key.js +23 -0
  119. package/dist/adt/stored-text/key.js.map +1 -0
  120. package/dist/adt/stored-text/reader.d.ts +52 -0
  121. package/dist/adt/stored-text/reader.d.ts.map +1 -0
  122. package/dist/adt/stored-text/reader.js +142 -0
  123. package/dist/adt/stored-text/reader.js.map +1 -0
  124. package/dist/adt/stored-text/source.d.ts +5 -0
  125. package/dist/adt/stored-text/source.d.ts.map +1 -0
  126. package/dist/adt/stored-text/source.js +284 -0
  127. package/dist/adt/stored-text/source.js.map +1 -0
  128. package/dist/adt/stored-text/types.d.ts +38 -0
  129. package/dist/adt/stored-text/types.d.ts.map +1 -0
  130. package/dist/adt/stored-text/types.js +2 -0
  131. package/dist/adt/stored-text/types.js.map +1 -0
  132. package/dist/adt/structure-hierarchy.d.ts.map +1 -1
  133. package/dist/adt/structure-hierarchy.js +11 -27
  134. package/dist/adt/structure-hierarchy.js.map +1 -1
  135. package/dist/adt/syntax-batch.d.ts +66 -0
  136. package/dist/adt/syntax-batch.d.ts.map +1 -0
  137. package/dist/adt/syntax-batch.js +115 -0
  138. package/dist/adt/syntax-batch.js.map +1 -0
  139. package/dist/adt/table-query.d.ts +3 -1
  140. package/dist/adt/table-query.d.ts.map +1 -1
  141. package/dist/adt/table-query.js +32 -4
  142. package/dist/adt/table-query.js.map +1 -1
  143. package/dist/adt/table-settings.d.ts +3 -0
  144. package/dist/adt/table-settings.d.ts.map +1 -1
  145. package/dist/adt/table-settings.js +11 -1
  146. package/dist/adt/table-settings.js.map +1 -1
  147. package/dist/adt/text-elements.js +1 -1
  148. package/dist/adt/text-elements.js.map +1 -1
  149. package/dist/adt/transport-diff.d.ts +16 -25
  150. package/dist/adt/transport-diff.d.ts.map +1 -1
  151. package/dist/adt/transport-diff.js +201 -103
  152. package/dist/adt/transport-diff.js.map +1 -1
  153. package/dist/adt/transport-locks.d.ts +7 -0
  154. package/dist/adt/transport-locks.d.ts.map +1 -0
  155. package/dist/adt/transport-locks.js +56 -0
  156. package/dist/adt/transport-locks.js.map +1 -0
  157. package/dist/adt/transport-review-budget.d.ts +15 -0
  158. package/dist/adt/transport-review-budget.d.ts.map +1 -0
  159. package/dist/adt/transport-review-budget.js +57 -0
  160. package/dist/adt/transport-review-budget.js.map +1 -0
  161. package/dist/adt/transport.d.ts +5 -2
  162. package/dist/adt/transport.d.ts.map +1 -1
  163. package/dist/adt/transport.js +8 -46
  164. package/dist/adt/transport.js.map +1 -1
  165. package/dist/adt/types.d.ts +1 -0
  166. package/dist/adt/types.d.ts.map +1 -1
  167. package/dist/adt/user-agent.d.ts +1 -1
  168. package/dist/adt/where-used-native.d.ts +22 -0
  169. package/dist/adt/where-used-native.d.ts.map +1 -0
  170. package/dist/adt/where-used-native.js +111 -0
  171. package/dist/adt/where-used-native.js.map +1 -0
  172. package/dist/adt/xml-parser.d.ts +2 -3
  173. package/dist/adt/xml-parser.d.ts.map +1 -1
  174. package/dist/adt/xml-parser.js +1 -91
  175. package/dist/adt/xml-parser.js.map +1 -1
  176. package/dist/aff/validator.d.ts.map +1 -1
  177. package/dist/aff/validator.js +8 -2
  178. package/dist/aff/validator.js.map +1 -1
  179. package/dist/authz/policy.d.ts.map +1 -1
  180. package/dist/authz/policy.js +10 -2
  181. package/dist/authz/policy.js.map +1 -1
  182. package/dist/cache/sqlite-driver.d.ts +24 -0
  183. package/dist/cache/sqlite-driver.d.ts.map +1 -0
  184. package/dist/cache/sqlite-driver.js +59 -0
  185. package/dist/cache/sqlite-driver.js.map +1 -0
  186. package/dist/cache/sqlite.d.ts +4 -2
  187. package/dist/cache/sqlite.d.ts.map +1 -1
  188. package/dist/cache/sqlite.js +5 -4
  189. package/dist/cache/sqlite.js.map +1 -1
  190. package/dist/cli-ide.d.ts +11 -0
  191. package/dist/cli-ide.d.ts.map +1 -0
  192. package/dist/cli-ide.js +69 -0
  193. package/dist/cli-ide.js.map +1 -0
  194. package/dist/cli.d.ts.map +1 -1
  195. package/dist/cli.js +9 -2
  196. package/dist/cli.js.map +1 -1
  197. package/dist/context/grep.d.ts +2 -0
  198. package/dist/context/grep.d.ts.map +1 -1
  199. package/dist/context/grep.js +8 -7
  200. package/dist/context/grep.js.map +1 -1
  201. package/dist/extract-sap-cookies.js +1 -0
  202. package/dist/extract-sap-cookies.js.map +1 -1
  203. package/dist/handlers/activate.d.ts.map +1 -1
  204. package/dist/handlers/activate.js +3 -0
  205. package/dist/handlers/activate.js.map +1 -1
  206. package/dist/handlers/application-log-input.d.ts +32 -0
  207. package/dist/handlers/application-log-input.d.ts.map +1 -0
  208. package/dist/handlers/application-log-input.js +34 -0
  209. package/dist/handlers/application-log-input.js.map +1 -0
  210. package/dist/handlers/application-log.d.ts +4 -0
  211. package/dist/handlers/application-log.d.ts.map +1 -0
  212. package/dist/handlers/application-log.js +14 -0
  213. package/dist/handlers/application-log.js.map +1 -0
  214. package/dist/handlers/cds-hints.d.ts +1 -1
  215. package/dist/handlers/cds-hints.d.ts.map +1 -1
  216. package/dist/handlers/cds-hints.js +21 -63
  217. package/dist/handlers/cds-hints.js.map +1 -1
  218. package/dist/handlers/context.d.ts.map +1 -1
  219. package/dist/handlers/context.js +7 -3
  220. package/dist/handlers/context.js.map +1 -1
  221. package/dist/handlers/diagnose.d.ts.map +1 -1
  222. package/dist/handlers/diagnose.js +10 -1
  223. package/dist/handlers/diagnose.js.map +1 -1
  224. package/dist/handlers/dispatch.d.ts +2 -1
  225. package/dist/handlers/dispatch.d.ts.map +1 -1
  226. package/dist/handlers/dispatch.js +63 -12
  227. package/dist/handlers/dispatch.js.map +1 -1
  228. package/dist/handlers/dump-filter-inputs.d.ts +38 -0
  229. package/dist/handlers/dump-filter-inputs.d.ts.map +1 -0
  230. package/dist/handlers/dump-filter-inputs.js +44 -0
  231. package/dist/handlers/dump-filter-inputs.js.map +1 -0
  232. package/dist/handlers/expanded-read.d.ts +24 -0
  233. package/dist/handlers/expanded-read.d.ts.map +1 -0
  234. package/dist/handlers/expanded-read.js +56 -0
  235. package/dist/handlers/expanded-read.js.map +1 -0
  236. package/dist/handlers/function-parameter-language.d.ts +5 -0
  237. package/dist/handlers/function-parameter-language.d.ts.map +1 -0
  238. package/dist/handlers/function-parameter-language.js +19 -0
  239. package/dist/handlers/function-parameter-language.js.map +1 -0
  240. package/dist/handlers/function-processing.d.ts +5 -0
  241. package/dist/handlers/function-processing.d.ts.map +1 -1
  242. package/dist/handlers/function-processing.js +5 -0
  243. package/dist/handlers/function-processing.js.map +1 -1
  244. package/dist/handlers/hyperfocused.d.ts.map +1 -1
  245. package/dist/handlers/hyperfocused.js +2 -1
  246. package/dist/handlers/hyperfocused.js.map +1 -1
  247. package/dist/handlers/long-text-input.d.ts +113 -0
  248. package/dist/handlers/long-text-input.d.ts.map +1 -0
  249. package/dist/handlers/long-text-input.js +113 -0
  250. package/dist/handlers/long-text-input.js.map +1 -0
  251. package/dist/handlers/long-text.d.ts +5 -0
  252. package/dist/handlers/long-text.d.ts.map +1 -0
  253. package/dist/handlers/long-text.js +122 -0
  254. package/dist/handlers/long-text.js.map +1 -0
  255. package/dist/handlers/navigate.d.ts.map +1 -1
  256. package/dist/handlers/navigate.js +8 -3
  257. package/dist/handlers/navigate.js.map +1 -1
  258. package/dist/handlers/object-types.d.ts.map +1 -1
  259. package/dist/handlers/object-types.js +12 -5
  260. package/dist/handlers/object-types.js.map +1 -1
  261. package/dist/handlers/query-input.d.ts +50 -0
  262. package/dist/handlers/query-input.d.ts.map +1 -0
  263. package/dist/handlers/query-input.js +59 -0
  264. package/dist/handlers/query-input.js.map +1 -0
  265. package/dist/handlers/query-tool.d.ts +11 -0
  266. package/dist/handlers/query-tool.d.ts.map +1 -0
  267. package/dist/handlers/query-tool.js +99 -0
  268. package/dist/handlers/query-tool.js.map +1 -0
  269. package/dist/handlers/query.d.ts +1 -1
  270. package/dist/handlers/query.d.ts.map +1 -1
  271. package/dist/handlers/query.js +7 -1
  272. package/dist/handlers/query.js.map +1 -1
  273. package/dist/handlers/read.d.ts +1 -0
  274. package/dist/handlers/read.d.ts.map +1 -1
  275. package/dist/handlers/read.js +62 -11
  276. package/dist/handlers/read.js.map +1 -1
  277. package/dist/handlers/schemas.d.ts +23 -4
  278. package/dist/handlers/schemas.d.ts.map +1 -1
  279. package/dist/handlers/schemas.js +82 -9
  280. package/dist/handlers/schemas.js.map +1 -1
  281. package/dist/handlers/syntax.d.ts.map +1 -1
  282. package/dist/handlers/syntax.js +8 -0
  283. package/dist/handlers/syntax.js.map +1 -1
  284. package/dist/handlers/tool-descriptions.js +2 -2
  285. package/dist/handlers/tool-descriptions.js.map +1 -1
  286. package/dist/handlers/tools.d.ts.map +1 -1
  287. package/dist/handlers/tools.js +81 -74
  288. package/dist/handlers/tools.js.map +1 -1
  289. package/dist/handlers/transport-review.d.ts +5 -0
  290. package/dist/handlers/transport-review.d.ts.map +1 -0
  291. package/dist/handlers/transport-review.js +108 -0
  292. package/dist/handlers/transport-review.js.map +1 -0
  293. package/dist/handlers/transport.d.ts.map +1 -1
  294. package/dist/handlers/transport.js +3 -58
  295. package/dist/handlers/transport.js.map +1 -1
  296. package/dist/handlers/where-used-details.d.ts +28 -0
  297. package/dist/handlers/where-used-details.d.ts.map +1 -0
  298. package/dist/handlers/where-used-details.js +67 -0
  299. package/dist/handlers/where-used-details.js.map +1 -0
  300. package/dist/handlers/where-used.d.ts +8 -3
  301. package/dist/handlers/where-used.d.ts.map +1 -1
  302. package/dist/handlers/where-used.js +40 -18
  303. package/dist/handlers/where-used.js.map +1 -1
  304. package/dist/handlers/write/create.d.ts.map +1 -1
  305. package/dist/handlers/write/create.js +15 -12
  306. package/dist/handlers/write/create.js.map +1 -1
  307. package/dist/handlers/write/pinned-activation.d.ts +8 -0
  308. package/dist/handlers/write/pinned-activation.d.ts.map +1 -0
  309. package/dist/handlers/write/pinned-activation.js +68 -0
  310. package/dist/handlers/write/pinned-activation.js.map +1 -0
  311. package/dist/handlers/write/pinned.d.ts +10 -0
  312. package/dist/handlers/write/pinned.d.ts.map +1 -0
  313. package/dist/handlers/write/pinned.js +202 -0
  314. package/dist/handlers/write/pinned.js.map +1 -0
  315. package/dist/handlers/write/update-delete.d.ts.map +1 -1
  316. package/dist/handlers/write/update-delete.js +5 -3
  317. package/dist/handlers/write/update-delete.js.map +1 -1
  318. package/dist/handlers/write-helpers.d.ts +2 -2
  319. package/dist/handlers/write-helpers.d.ts.map +1 -1
  320. package/dist/handlers/write-helpers.js +8 -6
  321. package/dist/handlers/write-helpers.js.map +1 -1
  322. package/dist/handlers/write.d.ts.map +1 -1
  323. package/dist/handlers/write.js +4 -1
  324. package/dist/handlers/write.js.map +1 -1
  325. package/dist/server/audit.d.ts +1 -0
  326. package/dist/server/audit.d.ts.map +1 -1
  327. package/dist/server/audit.js +49 -2
  328. package/dist/server/audit.js.map +1 -1
  329. package/dist/server/config.d.ts.map +1 -1
  330. package/dist/server/config.js +29 -1
  331. package/dist/server/config.js.map +1 -1
  332. package/dist/server/destination-registry.d.ts +14 -0
  333. package/dist/server/destination-registry.d.ts.map +1 -1
  334. package/dist/server/destination-registry.js +43 -4
  335. package/dist/server/destination-registry.js.map +1 -1
  336. package/dist/server/http.d.ts.map +1 -1
  337. package/dist/server/http.js +25 -5
  338. package/dist/server/http.js.map +1 -1
  339. package/dist/server/ide-links.d.ts +14 -0
  340. package/dist/server/ide-links.d.ts.map +1 -0
  341. package/dist/server/ide-links.js +146 -0
  342. package/dist/server/ide-links.js.map +1 -0
  343. package/dist/server/ide-request.d.ts +13 -0
  344. package/dist/server/ide-request.d.ts.map +1 -0
  345. package/dist/server/ide-request.js +14 -0
  346. package/dist/server/ide-request.js.map +1 -0
  347. package/dist/server/multi-target-authorization.d.ts +1 -1
  348. package/dist/server/multi-target-authorization.d.ts.map +1 -1
  349. package/dist/server/multi-target-authorization.js +5 -3
  350. package/dist/server/multi-target-authorization.js.map +1 -1
  351. package/dist/server/multi-target-catalog-enforced.d.ts +6 -1
  352. package/dist/server/multi-target-catalog-enforced.d.ts.map +1 -1
  353. package/dist/server/multi-target-catalog-enforced.js +3 -0
  354. package/dist/server/multi-target-catalog-enforced.js.map +1 -1
  355. package/dist/server/multi-target-catalog-projection.d.ts.map +1 -1
  356. package/dist/server/multi-target-catalog-projection.js +1 -0
  357. package/dist/server/multi-target-catalog-projection.js.map +1 -1
  358. package/dist/server/multi-target-catalog.d.ts.map +1 -1
  359. package/dist/server/multi-target-catalog.js +1 -0
  360. package/dist/server/multi-target-catalog.js.map +1 -1
  361. package/dist/server/multi-target-destination-config.d.ts +2 -0
  362. package/dist/server/multi-target-destination-config.d.ts.map +1 -1
  363. package/dist/server/multi-target-destination-config.js +18 -0
  364. package/dist/server/multi-target-destination-config.js.map +1 -1
  365. package/dist/server/multi-target-identity.d.ts.map +1 -1
  366. package/dist/server/multi-target-identity.js +4 -3
  367. package/dist/server/multi-target-identity.js.map +1 -1
  368. package/dist/server/multi-target-request-projection.d.ts +2 -0
  369. package/dist/server/multi-target-request-projection.d.ts.map +1 -1
  370. package/dist/server/multi-target-request-projection.js +2 -0
  371. package/dist/server/multi-target-request-projection.js.map +1 -1
  372. package/dist/server/multi-target-runtime.d.ts +5 -1
  373. package/dist/server/multi-target-runtime.d.ts.map +1 -1
  374. package/dist/server/multi-target-runtime.js +30 -3
  375. package/dist/server/multi-target-runtime.js.map +1 -1
  376. package/dist/server/multi-target-server.d.ts.map +1 -1
  377. package/dist/server/multi-target-server.js +42 -6
  378. package/dist/server/multi-target-server.js.map +1 -1
  379. package/dist/server/multi-target-tools.d.ts.map +1 -1
  380. package/dist/server/multi-target-tools.js +64 -7
  381. package/dist/server/multi-target-tools.js.map +1 -1
  382. package/dist/server/multi-target-write-surface.d.ts +9 -0
  383. package/dist/server/multi-target-write-surface.d.ts.map +1 -0
  384. package/dist/server/multi-target-write-surface.js +42 -0
  385. package/dist/server/multi-target-write-surface.js.map +1 -0
  386. package/dist/server/per-user-transport.d.ts +18 -0
  387. package/dist/server/per-user-transport.d.ts.map +1 -0
  388. package/dist/server/per-user-transport.js +72 -0
  389. package/dist/server/per-user-transport.js.map +1 -0
  390. package/dist/server/server-instructions.d.ts +2 -0
  391. package/dist/server/server-instructions.d.ts.map +1 -1
  392. package/dist/server/server-instructions.js +10 -12
  393. package/dist/server/server-instructions.js.map +1 -1
  394. package/dist/server/server.d.ts +3 -0
  395. package/dist/server/server.d.ts.map +1 -1
  396. package/dist/server/server.js +22 -8
  397. package/dist/server/server.js.map +1 -1
  398. package/dist/server/tool-auth.d.ts +1 -1
  399. package/dist/server/tool-auth.d.ts.map +1 -1
  400. package/dist/server/tool-auth.js +24 -4
  401. package/dist/server/tool-auth.js.map +1 -1
  402. package/dist/server/types.d.ts +7 -0
  403. package/dist/server/types.d.ts.map +1 -1
  404. package/dist/server/types.js +3 -0
  405. package/dist/server/types.js.map +1 -1
  406. package/dist/server/ui-state.d.ts.map +1 -1
  407. package/dist/server/ui-state.js +1 -0
  408. package/dist/server/ui-state.js.map +1 -1
  409. package/dist/version.d.ts +1 -1
  410. package/dist/version.js +1 -1
  411. package/package.json +14 -10
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Parse RFC 7231 `Retry-After` header into a delay in milliseconds.
3
+ *
4
+ * Accepts both forms allowed by the spec:
5
+ * - delta-seconds (e.g. `"5"`)
6
+ * - HTTP-date (e.g. `"Wed, 12 May 2026 14:30:00 GMT"`)
7
+ *
8
+ * On missing, NaN, malformed, past-date, or negative input, falls back to `fallbackMs`.
9
+ * Always clamps to `[0, 60_000]` ms so a misbehaving gateway can't stall us indefinitely
10
+ * and a too-small/past value can't degenerate into a hot retry loop.
11
+ *
12
+ * Returns `{ delayMs, source }` — `source: 'header' | 'fallback'` lets audit events
13
+ * record whether the delay came from the server or from our jitter floor (useful for
14
+ * capacity tuning).
15
+ */
16
+ export function parseRetryAfter(header, fallbackMs) {
17
+ const clamp = (ms) => Math.max(0, Math.min(60_000, ms));
18
+ if (header == null || header === '') {
19
+ return { delayMs: clamp(fallbackMs), source: 'fallback' };
20
+ }
21
+ const trimmed = header.trim();
22
+ // delta-seconds form: integer (and only digits, optionally signed)
23
+ if (/^-?\d+$/.test(trimmed)) {
24
+ const seconds = Number.parseInt(trimmed, 10);
25
+ if (Number.isFinite(seconds)) {
26
+ return { delayMs: clamp(seconds * 1000), source: 'header' };
27
+ }
28
+ return { delayMs: clamp(fallbackMs), source: 'fallback' };
29
+ }
30
+ // HTTP-date form
31
+ const epochMs = Date.parse(trimmed);
32
+ if (Number.isFinite(epochMs)) {
33
+ return { delayMs: clamp(epochMs - Date.now()), source: 'header' };
34
+ }
35
+ return { delayMs: clamp(fallbackMs), source: 'fallback' };
36
+ }
37
+ //# sourceMappingURL=http-retry-after.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-retry-after.js","sourceRoot":"","sources":["../../src/adt/http-retry-after.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAiC,EACjC,UAAkB;IAElB,MAAM,KAAK,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IACxE,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC5D,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,mEAAmE;IACnE,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC9D,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC5D,CAAC;IACD,iBAAiB;IACjB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAC5D,CAAC"}
@@ -9,6 +9,7 @@ import type { BTPProxyConfig } from '@arc-mcp/xsuaa-auth/btp';
9
9
  import { type AdtRequestOptions } from './http-deadline.js';
10
10
  import type { Semaphore } from './semaphore.js';
11
11
  export type { AdtRequestOptions } from './http-deadline.js';
12
+ export { parseRetryAfter } from './http-retry-after.js';
12
13
  /** Session type for ADT requests */
13
14
  export type SessionType = 'stateful' | 'stateless' | undefined;
14
15
  /** Configuration for the ADT HTTP client */
@@ -106,6 +107,8 @@ export declare class AdtHttpClient {
106
107
  private dbRetryInProgress;
107
108
  /** Set after a 401 clears stale cookies — triggers file reload on the next request */
108
109
  private cookiesCleared;
110
+ /** Keeps a cold client at one SAP security session (see security-session-gate.ts). */
111
+ private readonly securitySessionGate;
109
112
  /** Shared by stateful clones so one rejected Basic credential cannot fan out internally. */
110
113
  private readonly authenticationAttemptState;
111
114
  constructor(config: AdtHttpConfig, authenticationAttemptState?: AuthenticationAttemptState);
@@ -136,7 +139,11 @@ export declare class AdtHttpClient {
136
139
  * Creates a new client instance with the stateful session header,
137
140
  * shares the main client's request state, and closes the backend context.
138
141
  */
139
- withStatefulSession<T>(fn: (client: AdtHttpClient) => Promise<T>): Promise<T>;
142
+ withStatefulSession<T>(fn: (client: AdtHttpClient) => Promise<T>, cleanup?: {
143
+ timeoutMs: number;
144
+ noReplay: boolean;
145
+ onClose: (closed: boolean | undefined) => void;
146
+ }): Promise<T>;
140
147
  /** Close the SAP application context without changing the completed operation's result. */
141
148
  private closeStatefulSession;
142
149
  /** Core request method — wraps requestInner with optional concurrency limiter */
@@ -221,6 +228,8 @@ export declare class AdtHttpClient {
221
228
  * `config.cookies` and survive untouched. Returns undefined when empty.
222
229
  */
223
230
  private composeCookieHeader;
231
+ /** Read the current pair together after a wait or a response that can rotate the session. */
232
+ private refreshSessionHeaders;
224
233
  private storeCookies;
225
234
  /** Add SAP context query params unless the caller sends that context in headers. */
226
235
  private buildUrl;
@@ -239,6 +248,7 @@ export declare class AdtHttpClient {
239
248
  * interface is incompatible with npm undici@8 Agent/ProxyAgent instances.
240
249
  */
241
250
  private doFetch;
251
+ private sendRequest;
242
252
  /**
243
253
  * Execute an HTTP request through the BTP connectivity proxy using standard
244
254
  * HTTP proxy protocol (RFC 7230).
@@ -258,23 +268,4 @@ export declare class AdtHttpClient {
258
268
  */
259
269
  private doProxyRequest;
260
270
  }
261
- /**
262
- * Parse RFC 7231 `Retry-After` header into a delay in milliseconds.
263
- *
264
- * Accepts both forms allowed by the spec:
265
- * - delta-seconds (e.g. `"5"`)
266
- * - HTTP-date (e.g. `"Wed, 12 May 2026 14:30:00 GMT"`)
267
- *
268
- * On missing, NaN, malformed, past-date, or negative input, falls back to `fallbackMs`.
269
- * Always clamps to `[0, 60_000]` ms so a misbehaving gateway can't stall us indefinitely
270
- * and a too-small/past value can't degenerate into a hot retry loop.
271
- *
272
- * Returns `{ delayMs, source }` — `source: 'header' | 'fallback'` lets audit events
273
- * record whether the delay came from the server or from our jitter floor (useful for
274
- * capacity tuning).
275
- */
276
- export declare function parseRetryAfter(header: string | null | undefined, fallbackMs: number): {
277
- delayMs: number;
278
- source: 'header' | 'fallback';
279
- };
280
271
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/adt/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/adt/http.ts"],"names":[],"mappings":"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"}
package/dist/adt/http.js CHANGED
@@ -15,10 +15,13 @@ import { resolveCookies } from './cookies.js';
15
15
  import { resolveAcceptType, resolveContentType } from './discovery.js';
16
16
  import { AdtApiError, AdtNetworkError, AdtResponseLimitError } from './errors.js';
17
17
  import { awaitWithinRequestBudget, requestBudgetSignal, requestSignal, sleepWithinRequestBudget, throwIfRequestCancelled, withoutResponseBudget, } from './http-deadline.js';
18
+ import { parseRetryAfter } from './http-retry-after.js';
18
19
  import { prepareDataPreviewWireBody } from './http-wire-body.js';
19
20
  import { legacyContentHandlerFallback, rejectEmptyAdtHtmlResponse } from './legacy-content-handler.js';
20
21
  import { fetchWithAttemptBudget } from './request-attempt-budget.js';
22
+ import { hasSecuritySessionCookie, SecuritySessionGate } from './security-session-gate.js';
21
23
  import { resolveSapUserAgent } from './user-agent.js';
24
+ export { parseRetryAfter } from './http-retry-after.js';
22
25
  /**
23
26
  * Opt-in wire-level debug logging.
24
27
  *
@@ -104,6 +107,8 @@ export class AdtHttpClient {
104
107
  dbRetryInProgress = false;
105
108
  /** Set after a 401 clears stale cookies — triggers file reload on the next request */
106
109
  cookiesCleared = false;
110
+ /** Keeps a cold client at one SAP security session (see security-session-gate.ts). */
111
+ securitySessionGate = new SecuritySessionGate();
107
112
  /** Shared by stateful clones so one rejected Basic credential cannot fan out internally. */
108
113
  authenticationAttemptState;
109
114
  constructor(config, authenticationAttemptState) {
@@ -163,7 +168,7 @@ export class AdtHttpClient {
163
168
  * Creates a new client instance with the stateful session header,
164
169
  * shares the main client's request state, and closes the backend context.
165
170
  */
166
- async withStatefulSession(fn) {
171
+ async withStatefulSession(fn, cleanup) {
167
172
  const sessionConfig = {
168
173
  ...this.config,
169
174
  sessionType: 'stateful',
@@ -172,6 +177,7 @@ export class AdtHttpClient {
172
177
  // Share CSRF token and cookies so we don't need to re-fetch
173
178
  sessionClient.csrfToken = this.csrfToken;
174
179
  sessionClient.cookieJar = new Map(this.cookieJar);
180
+ sessionClient.cookieJar.delete('sap-contextid'); // A new write must open its own application context.
175
181
  sessionClient.discoveryMap = this.discoveryMap;
176
182
  sessionClient.negotiatedHeaders = new Map(this.negotiatedHeaders);
177
183
  sessionClient.reuseStatefulProxyClient = true;
@@ -179,7 +185,14 @@ export class AdtHttpClient {
179
185
  return await fn(sessionClient);
180
186
  }
181
187
  finally {
182
- await sessionClient.closeStatefulSession();
188
+ const closed = await sessionClient.closeStatefulSession(cleanup
189
+ ? {
190
+ deadline: Date.now() + cleanup.timeoutMs,
191
+ retryTransientErrors: false,
192
+ noReplay: cleanup.noReplay,
193
+ }
194
+ : undefined);
195
+ cleanup?.onClose(closed);
183
196
  try {
184
197
  await sessionClient.statefulProxyClient?.close();
185
198
  }
@@ -189,7 +202,7 @@ export class AdtHttpClient {
189
202
  }
190
203
  }
191
204
  /** Close the SAP application context without changing the completed operation's result. */
192
- async closeStatefulSession() {
205
+ async closeStatefulSession(options) {
193
206
  const contextId = this.cookieJar.get('sap-contextid');
194
207
  if (!contextId || contextId === '0')
195
208
  return;
@@ -198,24 +211,26 @@ export class AdtHttpClient {
198
211
  this.config.sessionType = 'stateless';
199
212
  try {
200
213
  try {
201
- await this.get('/sap/bc/adt/core/http/sessions', { Accept: '*/*', 'sap-adt-purpose': 'close-session', 'sap-contextid': contextId }, { probe: true });
202
- return;
214
+ await this.get('/sap/bc/adt/core/http/sessions', { Accept: '*/*', 'sap-adt-purpose': 'close-session', 'sap-contextid': contextId }, { probe: true, ...options });
215
+ return true;
203
216
  }
204
217
  catch (error) {
205
218
  if (!(error instanceof AdtApiError && error.statusCode === 404))
206
219
  throw error;
207
220
  }
208
221
  // NW 7.50 lacks the close resource; its stateful-header backport closes on discovery instead.
209
- await this.head('/sap/bc/adt/core/discovery', { Accept: '*/*' }, { probe: true });
222
+ await this.head('/sap/bc/adt/core/discovery', { Accept: '*/*' }, { probe: true, ...options });
223
+ return true;
210
224
  }
211
225
  catch (error) {
212
226
  // NW 7.50 can return 400 after closing. The reset cookie confirms that cleanup succeeded.
213
227
  if (this.cookieJar.get('sap-contextid') === '0')
214
- return;
228
+ return true;
215
229
  // Preserve the write result/error and keep SAP response text out of cleanup warnings.
216
230
  logger.warn('Failed to close stateful ADT session.', {
217
231
  statusCode: error instanceof AdtApiError ? error.statusCode : undefined,
218
232
  });
233
+ return false;
219
234
  }
220
235
  }
221
236
  /** Core request method — wraps requestInner with optional concurrency limiter */
@@ -236,6 +251,8 @@ export class AdtHttpClient {
236
251
  }
237
252
  if (!options?.signal && options?.deadline === undefined)
238
253
  throw error;
254
+ if (options?.signal?.aborted)
255
+ throwIfRequestCancelled(options);
239
256
  const cause = error instanceof Error ? error : new Error(String(error));
240
257
  throw new AdtNetworkError(cause.message, cause);
241
258
  }
@@ -364,15 +381,13 @@ export class AdtHttpClient {
364
381
  const url = this.buildUrl(path, sapContextInHeaders);
365
382
  const httpStart = Date.now();
366
383
  // Per-request guards to prevent infinite retry loops
367
- const retryTransientErrors = options?.retryTransientErrors !== false;
384
+ const retryTransientErrors = options?.noReplay !== true && options?.retryTransientErrors !== false;
368
385
  let negotiationRetried = false;
369
386
  let authRetried = false;
370
387
  let retried429 = false;
371
388
  try {
372
- let response = await this.doFetch(url, method, headers, wireBody, options);
389
+ let response = await this.doFetch(url, method, headers, wireBody, options, this.config.retryUnauthorized !== false && options?.noReplay !== true);
373
390
  let responseBody = await response.text();
374
- // Persist any Set-Cookie headers from the response
375
- this.storeCookies(response);
376
391
  // Detect broken DB connection on the assigned work process.
377
392
  // SAP's ICM routes all requests with the same session cookie to the same
378
393
  // work process. If that WP has a broken HANA connection, every request fails
@@ -414,7 +429,6 @@ export class AdtHttpClient {
414
429
  }
415
430
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
416
431
  const retryBody = await retryResp.text();
417
- this.storeCookies(retryResp);
418
432
  const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
419
433
  logger.emitAudit({
420
434
  timestamp: new Date().toISOString(),
@@ -448,9 +462,9 @@ export class AdtHttpClient {
448
462
  errorBody: `503 Service Unavailable — retrying in ${Math.round(jitterMs)}ms (${source})`,
449
463
  });
450
464
  await sleepWithinRequestBudget(jitterMs, options);
465
+ this.refreshSessionHeaders(method, headers);
451
466
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
452
467
  const retryBody = await retryResp.text();
453
- this.storeCookies(retryResp);
454
468
  logger.emitAudit({
455
469
  timestamp: new Date().toISOString(),
456
470
  level: retryResp.status === 503 ? 'warn' : 'info',
@@ -480,9 +494,9 @@ export class AdtHttpClient {
480
494
  errorBody: `429 Too Many Requests — retrying in ${Math.round(jitterMs)}ms (${source})`,
481
495
  });
482
496
  await sleepWithinRequestBudget(jitterMs, options);
497
+ this.refreshSessionHeaders(method, headers);
483
498
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
484
499
  const retryBody = await retryResp.text();
485
- this.storeCookies(retryResp);
486
500
  logger.emitAudit({
487
501
  timestamp: new Date().toISOString(),
488
502
  level: retryResp.status === 429 ? 'warn' : 'info',
@@ -499,7 +513,10 @@ export class AdtHttpClient {
499
513
  // Uses per-request guard (not instance-level) so concurrent requests each get their own retry.
500
514
  // On success, reassigns response/responseBody and falls through to downstream handlers
501
515
  // (403 CSRF, 406/415 negotiation) so combined-failure recovery works.
502
- if (response.status === 401 && !authRetried && this.config.retryUnauthorized !== false) {
516
+ if (response.status === 401 &&
517
+ !authRetried &&
518
+ this.config.retryUnauthorized !== false &&
519
+ options?.noReplay !== true) {
503
520
  authRetried = true;
504
521
  logger.emitAudit({
505
522
  timestamp: new Date().toISOString(),
@@ -511,8 +528,6 @@ export class AdtHttpClient {
511
528
  durationMs: Date.now() - httpStart,
512
529
  errorBody: '401 session expired — resetting session and retrying',
513
530
  });
514
- // Clear session to force fresh authentication
515
- this.resetSession();
516
531
  // Pick up an out-of-band rotated cookie file so the call that observes the
517
532
  // expiry can recover; the lazy `cookiesCleared` reload stays the fallback.
518
533
  // `cookieFile`, not `isCookieAuthMode()` — cookieString has nothing to re-read,
@@ -542,7 +557,6 @@ export class AdtHttpClient {
542
557
  }
543
558
  response = await this.doFetch(url, method, headers, wireBody, options);
544
559
  responseBody = await response.text();
545
- this.storeCookies(response);
546
560
  logger.emitAudit({
547
561
  timestamp: new Date().toISOString(),
548
562
  level: 'info',
@@ -561,7 +575,7 @@ export class AdtHttpClient {
561
575
  // Fall through to downstream handlers (403/406/415/normal)
562
576
  }
563
577
  // Handle CSRF token refresh on 403 (modifying requests only)
564
- if (response.status === 403 && isModifyingMethod(method)) {
578
+ if (options?.noReplay !== true && response.status === 403 && isModifyingMethod(method)) {
565
579
  await this.fetchCsrfToken(withoutResponseBudget(options));
566
580
  headers['X-CSRF-Token'] = this.csrfToken;
567
581
  // Update cookie header after CSRF fetch may have set new cookies. Use the
@@ -573,12 +587,13 @@ export class AdtHttpClient {
573
587
  }
574
588
  response = await this.doFetch(url, method, headers, wireBody, options);
575
589
  responseBody = await response.text();
576
- this.storeCookies(response);
577
590
  // A refreshed session can still need legacy content negotiation below (#996).
578
591
  }
579
592
  // Retry negotiation once, including the narrowly matched NW 7.40 handler error.
580
593
  const legacyFallback = legacyContentHandlerFallback(response.status, responseBody, method, negotiationKey, headers);
581
- if ((response.status === 406 || response.status === 415 || legacyFallback) && !negotiationRetried) {
594
+ if (options?.noReplay !== true &&
595
+ (response.status === 406 || response.status === 415 || legacyFallback) &&
596
+ !negotiationRetried) {
582
597
  negotiationRetried = true;
583
598
  const fallbackHeaders = { ...headers };
584
599
  let headersChanged = false;
@@ -621,14 +636,9 @@ export class AdtHttpClient {
621
636
  durationMs: Date.now() - httpStart,
622
637
  errorBody: `Content negotiation ${response.status} — retrying with fallback headers`,
623
638
  });
639
+ this.refreshSessionHeaders(method, fallbackHeaders);
624
640
  const retryResp = await this.doFetch(url, method, fallbackHeaders, wireBody, options);
625
641
  const retryBody = await retryResp.text();
626
- this.storeCookies(retryResp);
627
- // Store CSRF token from retry response
628
- const retryToken = retryResp.headers.get('x-csrf-token');
629
- if (retryToken && retryToken !== 'Required') {
630
- this.csrfToken = retryToken;
631
- }
632
642
  const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
633
643
  const currentContentType = contentType ?? headers['Content-Type'];
634
644
  const negotiated = {};
@@ -656,11 +666,6 @@ export class AdtHttpClient {
656
666
  }
657
667
  // No meaningful header change — fall through to normal error handling
658
668
  }
659
- // Store CSRF token from response
660
- const responseToken = response.headers.get('x-csrf-token');
661
- if (responseToken && responseToken !== 'Required') {
662
- this.csrfToken = responseToken;
663
- }
664
669
  const result = this.handleResponse(response.status, response.headers, responseBody, path, expectBody);
665
670
  logger.emitAudit({
666
671
  timestamp: new Date().toISOString(),
@@ -711,6 +716,8 @@ export class AdtHttpClient {
711
716
  }
712
717
  if (err instanceof AdtNetworkError || err instanceof AdtResponseLimitError)
713
718
  throw err;
719
+ if (options?.signal?.aborted)
720
+ throwIfRequestCancelled(options);
714
721
  const message = err instanceof Error ? err.message : String(err);
715
722
  throw new AdtNetworkError(message, err instanceof Error ? err : undefined);
716
723
  }
@@ -818,12 +825,6 @@ export class AdtHttpClient {
818
825
  if (this.cookiesCleared && this.isCookieAuthMode()) {
819
826
  this.reloadCookiesFromSource();
820
827
  }
821
- // A token only counts as proof when the response itself succeeded: SAP returns one on
822
- // failures too, and the old code accepted a token from a 401 — masking the auth error.
823
- const usableToken = (response) => {
824
- const token = response.headers.get('x-csrf-token')?.trim();
825
- return response.ok && token && token.toLowerCase() !== 'required' ? token : undefined;
826
- };
827
828
  // Every probe keeps the same identity, current cookies and caller's request budget.
828
829
  const probe = async (method) => {
829
830
  const cookieHeader = this.composeCookieHeader();
@@ -833,7 +834,6 @@ export class AdtHttpClient {
833
834
  delete headers.Cookie;
834
835
  const started = Date.now();
835
836
  const response = await this.doFetch(this.buildUrl(path), method, headers, undefined, options);
836
- this.storeCookies(response);
837
837
  logger.emitAudit({
838
838
  timestamp: new Date().toISOString(),
839
839
  level: 'debug',
@@ -842,11 +842,11 @@ export class AdtHttpClient {
842
842
  path,
843
843
  statusCode: response.status,
844
844
  durationMs: Date.now() - started,
845
- success: !!usableToken(response),
846
- adtMode: this.config.sessionType ?? 'unspecified',
847
- hasContext: /(?:^|;\s*)sap-contextid=/.test(cookieHeader ?? ''),
845
+ success: !!usableCsrfToken(response),
846
+ adtMode: headers['X-sap-adt-sessiontype'] === undefined ? 'unspecified' : (this.config.sessionType ?? 'unspecified'),
847
+ hasContext: /(?:^|;\s*)sap-contextid=/.test(headers.Cookie ?? ''),
848
848
  });
849
- if (method === 'GET' && response.status === 200 && !usableToken(response)) {
849
+ if (method === 'GET' && response.status === 200 && !usableCsrfToken(response)) {
850
850
  // Check login pages, but preserve the header-only legacy discovery fallback.
851
851
  this.handleResponse(response.status, response.headers, await response.text(), path, false);
852
852
  }
@@ -877,16 +877,23 @@ export class AdtHttpClient {
877
877
  // The tested 7.50/7.58/8.16 systems returned HEAD 400 with a token; GET returned 200.
878
878
  // Retry these HEAD refusals or a successful response without a token on the same path.
879
879
  // A successful HEAD with a usable token remains the one-request fast path.
880
- if ([400, 403, 405].includes(response.status) || (response.ok && !usableToken(response))) {
880
+ const headStatus = response.status;
881
+ if ([400, 403, 405].includes(response.status) || (response.ok && !usableCsrfToken(response))) {
882
+ response = await probe('GET');
883
+ }
884
+ // Both stateful discovery probes can fail on affected routes (#1044). Bootstrap once
885
+ // without that header; keep identity/cookies and subsequent lock/write requests stateful.
886
+ if (this.config.sessionType === 'stateful' && headStatus === 400 && response.status === 400) {
887
+ delete headers['X-sap-adt-sessiontype'];
881
888
  response = await probe('GET');
882
889
  }
883
890
  // Older ADT handlers may return an empty 200 for a missing core resource (#817).
884
891
  // A real auth/server failure must not be hidden by trying another endpoint.
885
- if (response.status === 404 || response.status === 405 || (response.ok && !usableToken(response))) {
892
+ if (response.status === 404 || response.status === 405 || (response.ok && !usableCsrfToken(response))) {
886
893
  path = '/sap/bc/adt/discovery';
887
894
  response = await probe('GET');
888
895
  }
889
- const token = usableToken(response);
896
+ const token = usableCsrfToken(response);
890
897
  if (!token) {
891
898
  if (response.status === 401) {
892
899
  if (this.isCookieAuthMode())
@@ -899,12 +906,13 @@ export class AdtHttpClient {
899
906
  }
900
907
  throw new AdtApiError(`No CSRF token in response (HTTP ${response.status})`, response.status, path);
901
908
  }
902
- this.csrfToken = token;
903
909
  return path;
904
910
  }
905
911
  catch (err) {
906
912
  if (err instanceof AdtApiError || err instanceof AdtNetworkError)
907
913
  throw err;
914
+ if (options?.signal?.aborted)
915
+ throwIfRequestCancelled(options);
908
916
  const message = err instanceof Error ? err.message : String(err);
909
917
  throw new AdtNetworkError(`CSRF token fetch failed: ${message}`, err instanceof Error ? err : undefined);
910
918
  }
@@ -943,8 +951,7 @@ export class AdtHttpClient {
943
951
  */
944
952
  clearCookiesAndMark() {
945
953
  this.config.cookies = {};
946
- this.cookieJar.clear();
947
- this.csrfToken = '';
954
+ this.resetSession();
948
955
  this.cookiesCleared = true;
949
956
  }
950
957
  /**
@@ -993,6 +1000,7 @@ export class AdtHttpClient {
993
1000
  resetSession() {
994
1001
  this.cookieJar.clear();
995
1002
  this.csrfToken = '';
1003
+ this.securitySessionGate.reset();
996
1004
  }
997
1005
  /**
998
1006
  * Build the `Cookie` request header by merging the static `config.cookies`
@@ -1025,11 +1033,18 @@ export class AdtHttpClient {
1025
1033
  return undefined;
1026
1034
  return Array.from(merged, ([name, value]) => `${name}=${value}`).join('; ');
1027
1035
  }
1036
+ /** Read the current pair together after a wait or a response that can rotate the session. */
1037
+ refreshSessionHeaders(method, headers) {
1038
+ const cookie = this.composeCookieHeader();
1039
+ if (cookie)
1040
+ headers.Cookie = cookie;
1041
+ else
1042
+ delete headers.Cookie;
1043
+ if (isModifyingMethod(method))
1044
+ headers['X-CSRF-Token'] = this.csrfToken;
1045
+ }
1028
1046
  storeCookies(response) {
1029
- const setCookieHeaders = response.headers.getSetCookie();
1030
- if (!setCookieHeaders || setCookieHeaders.length === 0)
1031
- return;
1032
- for (const cookie of setCookieHeaders) {
1047
+ for (const cookie of response.headers.getSetCookie() ?? []) {
1033
1048
  // Set-Cookie: name=value; Path=/; HttpOnly; ...
1034
1049
  const nameValue = cookie.split(';')[0];
1035
1050
  if (!nameValue)
@@ -1090,7 +1105,37 @@ export class AdtHttpClient {
1090
1105
  * Node 22's built-in fetch embeds an older undici version whose dispatcher
1091
1106
  * interface is incompatible with npm undici@8 Agent/ProxyAgent instances.
1092
1107
  */
1093
- async doFetch(url, method, headers, body, options) {
1108
+ async doFetch(url, method, headers, body, options, resetOnUnauthorized = false) {
1109
+ const cookieNames = () => [...this.cookieJar.keys(), ...Object.keys(this.config.cookies ?? {})];
1110
+ const response = await this.securitySessionGate.run(() => hasSecuritySessionCookie(cookieNames()), async (waited) => {
1111
+ const generation = this.securitySessionGate.generation;
1112
+ if (waited) {
1113
+ // A preceding response may have replaced both fields while this send waited.
1114
+ // Keep the refreshed pair for this logical request's negotiation/retry paths too.
1115
+ this.refreshSessionHeaders(method, headers);
1116
+ }
1117
+ const response = await this.sendRequest(url, method, headers, body, options);
1118
+ const fetchingCsrf = headers['X-CSRF-Token']?.toLowerCase() === 'fetch';
1119
+ if (generation === this.securitySessionGate.generation) {
1120
+ // Store once at the headers boundary, before releasing the bootstrap owner.
1121
+ this.storeCookies(response);
1122
+ // Ordinary responses (including 404) can carry a token without proving a Fetch probe succeeded.
1123
+ const token = fetchingCsrf ? usableCsrfToken(response) : response.headers.get('x-csrf-token');
1124
+ if (token && token !== 'Required')
1125
+ this.csrfToken = token;
1126
+ // Reset before releasing waiters; a slow 401 body must not clear their new session.
1127
+ if (resetOnUnauthorized && response.status === 401)
1128
+ this.resetSession();
1129
+ }
1130
+ else if (fetchingCsrf) {
1131
+ await response.body?.cancel();
1132
+ throw new AdtNetworkError('SAP session changed during CSRF bootstrap. Retry the request.');
1133
+ }
1134
+ return response;
1135
+ }, options);
1136
+ return prepareBoundedResponse(response, url, options);
1137
+ }
1138
+ async sendRequest(url, method, headers, body, options) {
1094
1139
  throwIfRequestCancelled(options);
1095
1140
  // Forward the caller's W3C trace context to SAP so one trace spans agent → ARC-1 → SAP.
1096
1141
  // Empty unless the MCP client sent a valid `traceparent`; ARC-1 never originates a trace.
@@ -1117,7 +1162,7 @@ export class AdtHttpClient {
1117
1162
  ...(dispatcher ? { dispatcher } : {}),
1118
1163
  }, options?.attemptBudget));
1119
1164
  }
1120
- return prepareBoundedResponse(response, url, options);
1165
+ return response;
1121
1166
  }
1122
1167
  /**
1123
1168
  * Execute an HTTP request through the BTP connectivity proxy using standard
@@ -1201,41 +1246,10 @@ export class AdtHttpClient {
1201
1246
  function isModifyingMethod(method) {
1202
1247
  return ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method.toUpperCase());
1203
1248
  }
1204
- /**
1205
- * Parse RFC 7231 `Retry-After` header into a delay in milliseconds.
1206
- *
1207
- * Accepts both forms allowed by the spec:
1208
- * - delta-seconds (e.g. `"5"`)
1209
- * - HTTP-date (e.g. `"Wed, 12 May 2026 14:30:00 GMT"`)
1210
- *
1211
- * On missing, NaN, malformed, past-date, or negative input, falls back to `fallbackMs`.
1212
- * Always clamps to `[0, 60_000]` ms so a misbehaving gateway can't stall us indefinitely
1213
- * and a too-small/past value can't degenerate into a hot retry loop.
1214
- *
1215
- * Returns `{ delayMs, source }` — `source: 'header' | 'fallback'` lets audit events
1216
- * record whether the delay came from the server or from our jitter floor (useful for
1217
- * capacity tuning).
1218
- */
1219
- export function parseRetryAfter(header, fallbackMs) {
1220
- const clamp = (ms) => Math.max(0, Math.min(60_000, ms));
1221
- if (header == null || header === '') {
1222
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1223
- }
1224
- const trimmed = header.trim();
1225
- // delta-seconds form: integer (and only digits, optionally signed)
1226
- if (/^-?\d+$/.test(trimmed)) {
1227
- const seconds = Number.parseInt(trimmed, 10);
1228
- if (Number.isFinite(seconds)) {
1229
- return { delayMs: clamp(seconds * 1000), source: 'header' };
1230
- }
1231
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1232
- }
1233
- // HTTP-date form
1234
- const epochMs = Date.parse(trimmed);
1235
- if (Number.isFinite(epochMs)) {
1236
- return { delayMs: clamp(epochMs - Date.now()), source: 'header' };
1237
- }
1238
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1249
+ /** A token on an unsuccessful response is not proof of authentication. */
1250
+ function usableCsrfToken(response) {
1251
+ const token = response.headers.get('x-csrf-token')?.trim();
1252
+ return response.ok && token && token.toLowerCase() !== 'required' ? token : undefined;
1239
1253
  }
1240
1254
  /**
1241
1255
  * Distinguish a real SAP logon page from a legitimate HTML response payload.