arc-1 1.5.2 → 1.7.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 (472) hide show
  1. package/README.md +26 -16
  2. package/bin/arc1-source.js +83 -0
  3. package/dist/adt/accept-fallback.d.ts +4 -0
  4. package/dist/adt/accept-fallback.d.ts.map +1 -0
  5. package/dist/adt/accept-fallback.js +27 -0
  6. package/dist/adt/accept-fallback.js.map +1 -0
  7. package/dist/adt/api-release.d.ts +40 -0
  8. package/dist/adt/api-release.d.ts.map +1 -0
  9. package/dist/adt/api-release.js +224 -0
  10. package/dist/adt/api-release.js.map +1 -0
  11. package/dist/adt/application-log.d.ts +36 -0
  12. package/dist/adt/application-log.d.ts.map +1 -0
  13. package/dist/adt/application-log.js +143 -0
  14. package/dist/adt/application-log.js.map +1 -0
  15. package/dist/adt/authorization-trace.d.ts.map +1 -1
  16. package/dist/adt/authorization-trace.js +2 -1
  17. package/dist/adt/authorization-trace.js.map +1 -1
  18. package/dist/adt/class-structure.d.ts +2 -1
  19. package/dist/adt/class-structure.d.ts.map +1 -1
  20. package/dist/adt/class-structure.js +28 -10
  21. package/dist/adt/class-structure.js.map +1 -1
  22. package/dist/adt/client.d.ts +12 -6
  23. package/dist/adt/client.d.ts.map +1 -1
  24. package/dist/adt/client.js +32 -49
  25. package/dist/adt/client.js.map +1 -1
  26. package/dist/adt/codeintel.d.ts +9 -23
  27. package/dist/adt/codeintel.d.ts.map +1 -1
  28. package/dist/adt/codeintel.js +14 -34
  29. package/dist/adt/codeintel.js.map +1 -1
  30. package/dist/adt/ddic-xml.d.ts +5 -3
  31. package/dist/adt/ddic-xml.d.ts.map +1 -1
  32. package/dist/adt/ddic-xml.js +14 -0
  33. package/dist/adt/ddic-xml.js.map +1 -1
  34. package/dist/adt/devtools.d.ts +8 -1
  35. package/dist/adt/devtools.d.ts.map +1 -1
  36. package/dist/adt/devtools.js +94 -40
  37. package/dist/adt/devtools.js.map +1 -1
  38. package/dist/adt/diagnostics.d.ts +2 -0
  39. package/dist/adt/diagnostics.d.ts.map +1 -1
  40. package/dist/adt/diagnostics.js +10 -8
  41. package/dist/adt/diagnostics.js.map +1 -1
  42. package/dist/adt/enhancement-impl.d.ts +125 -0
  43. package/dist/adt/enhancement-impl.d.ts.map +1 -0
  44. package/dist/adt/enhancement-impl.js +408 -0
  45. package/dist/adt/enhancement-impl.js.map +1 -0
  46. package/dist/adt/enhancements.d.ts.map +1 -1
  47. package/dist/adt/enhancements.js +4 -2
  48. package/dist/adt/enhancements.js.map +1 -1
  49. package/dist/adt/enho-filter.d.ts +49 -0
  50. package/dist/adt/enho-filter.d.ts.map +1 -0
  51. package/dist/adt/enho-filter.js +229 -0
  52. package/dist/adt/enho-filter.js.map +1 -0
  53. package/dist/adt/errors.d.ts +5 -1
  54. package/dist/adt/errors.d.ts.map +1 -1
  55. package/dist/adt/errors.js +32 -8
  56. package/dist/adt/errors.js.map +1 -1
  57. package/dist/adt/features.d.ts +3 -9
  58. package/dist/adt/features.d.ts.map +1 -1
  59. package/dist/adt/features.js +24 -8
  60. package/dist/adt/features.js.map +1 -1
  61. package/dist/adt/feed-schema.d.ts +32 -0
  62. package/dist/adt/feed-schema.d.ts.map +1 -0
  63. package/dist/adt/feed-schema.js +123 -0
  64. package/dist/adt/feed-schema.js.map +1 -0
  65. package/dist/adt/fm-parameter-docs.d.ts +7 -0
  66. package/dist/adt/fm-parameter-docs.d.ts.map +1 -0
  67. package/dist/adt/fm-parameter-docs.js +134 -0
  68. package/dist/adt/fm-parameter-docs.js.map +1 -0
  69. package/dist/adt/fm-signature.d.ts +8 -1
  70. package/dist/adt/fm-signature.d.ts.map +1 -1
  71. package/dist/adt/fm-signature.js +37 -28
  72. package/dist/adt/fm-signature.js.map +1 -1
  73. package/dist/adt/http-deadline.d.ts.map +1 -1
  74. package/dist/adt/http-deadline.js +4 -1
  75. package/dist/adt/http-deadline.js.map +1 -1
  76. package/dist/adt/http-retry-after.d.ts +20 -0
  77. package/dist/adt/http-retry-after.d.ts.map +1 -0
  78. package/dist/adt/http-retry-after.js +37 -0
  79. package/dist/adt/http-retry-after.js.map +1 -0
  80. package/dist/adt/http.d.ts +7 -20
  81. package/dist/adt/http.d.ts.map +1 -1
  82. package/dist/adt/http.js +112 -135
  83. package/dist/adt/http.js.map +1 -1
  84. package/dist/adt/include-expansion.d.ts +143 -0
  85. package/dist/adt/include-expansion.d.ts.map +1 -0
  86. package/dist/adt/include-expansion.js +475 -0
  87. package/dist/adt/include-expansion.js.map +1 -0
  88. package/dist/adt/internal-data-operations.d.ts +3 -3
  89. package/dist/adt/internal-data-operations.d.ts.map +1 -1
  90. package/dist/adt/internal-data-operations.js +9 -2
  91. package/dist/adt/internal-data-operations.js.map +1 -1
  92. package/dist/adt/legacy-content-handler.d.ts +2 -0
  93. package/dist/adt/legacy-content-handler.d.ts.map +1 -1
  94. package/dist/adt/legacy-content-handler.js +13 -1
  95. package/dist/adt/legacy-content-handler.js.map +1 -1
  96. package/dist/adt/package-contents.d.ts +5 -0
  97. package/dist/adt/package-contents.d.ts.map +1 -1
  98. package/dist/adt/package-contents.js +31 -0
  99. package/dist/adt/package-contents.js.map +1 -1
  100. package/dist/adt/rap-generate.d.ts +2 -4
  101. package/dist/adt/rap-generate.d.ts.map +1 -1
  102. package/dist/adt/rap-generate.js +2 -4
  103. package/dist/adt/rap-generate.js.map +1 -1
  104. package/dist/adt/revision-feed.d.ts +8 -0
  105. package/dist/adt/revision-feed.d.ts.map +1 -0
  106. package/dist/adt/revision-feed.js +108 -0
  107. package/dist/adt/revision-feed.js.map +1 -0
  108. package/dist/adt/security-session-gate.d.ts +23 -0
  109. package/dist/adt/security-session-gate.d.ts.map +1 -0
  110. package/dist/adt/security-session-gate.js +56 -0
  111. package/dist/adt/security-session-gate.js.map +1 -0
  112. package/dist/adt/server-driven.d.ts +12 -1
  113. package/dist/adt/server-driven.d.ts.map +1 -1
  114. package/dist/adt/server-driven.js +22 -4
  115. package/dist/adt/server-driven.js.map +1 -1
  116. package/dist/adt/source-diff.d.ts +4 -1
  117. package/dist/adt/source-diff.d.ts.map +1 -1
  118. package/dist/adt/source-diff.js +5 -3
  119. package/dist/adt/source-diff.js.map +1 -1
  120. package/dist/adt/stored-text/chunks.d.ts +8 -0
  121. package/dist/adt/stored-text/chunks.d.ts.map +1 -0
  122. package/dist/adt/stored-text/chunks.js +55 -0
  123. package/dist/adt/stored-text/chunks.js.map +1 -0
  124. package/dist/adt/stored-text/decoder.d.ts +31 -0
  125. package/dist/adt/stored-text/decoder.d.ts.map +1 -0
  126. package/dist/adt/stored-text/decoder.js +319 -0
  127. package/dist/adt/stored-text/decoder.js.map +1 -0
  128. package/dist/adt/stored-text/errors.d.ts +10 -0
  129. package/dist/adt/stored-text/errors.d.ts.map +1 -0
  130. package/dist/adt/stored-text/errors.js +10 -0
  131. package/dist/adt/stored-text/errors.js.map +1 -0
  132. package/dist/adt/stored-text/index.d.ts +7 -0
  133. package/dist/adt/stored-text/index.d.ts.map +1 -0
  134. package/dist/adt/stored-text/index.js +6 -0
  135. package/dist/adt/stored-text/index.js.map +1 -0
  136. package/dist/adt/stored-text/key.d.ts +3 -0
  137. package/dist/adt/stored-text/key.d.ts.map +1 -0
  138. package/dist/adt/stored-text/key.js +23 -0
  139. package/dist/adt/stored-text/key.js.map +1 -0
  140. package/dist/adt/stored-text/reader.d.ts +52 -0
  141. package/dist/adt/stored-text/reader.d.ts.map +1 -0
  142. package/dist/adt/stored-text/reader.js +142 -0
  143. package/dist/adt/stored-text/reader.js.map +1 -0
  144. package/dist/adt/stored-text/source.d.ts +5 -0
  145. package/dist/adt/stored-text/source.d.ts.map +1 -0
  146. package/dist/adt/stored-text/source.js +284 -0
  147. package/dist/adt/stored-text/source.js.map +1 -0
  148. package/dist/adt/stored-text/types.d.ts +38 -0
  149. package/dist/adt/stored-text/types.d.ts.map +1 -0
  150. package/dist/adt/stored-text/types.js +2 -0
  151. package/dist/adt/stored-text/types.js.map +1 -0
  152. package/dist/adt/structure-hierarchy.d.ts.map +1 -1
  153. package/dist/adt/structure-hierarchy.js +11 -27
  154. package/dist/adt/structure-hierarchy.js.map +1 -1
  155. package/dist/adt/syntax-batch.d.ts +66 -0
  156. package/dist/adt/syntax-batch.d.ts.map +1 -0
  157. package/dist/adt/syntax-batch.js +115 -0
  158. package/dist/adt/syntax-batch.js.map +1 -0
  159. package/dist/adt/table-index.d.ts +23 -0
  160. package/dist/adt/table-index.d.ts.map +1 -0
  161. package/dist/adt/table-index.js +69 -0
  162. package/dist/adt/table-index.js.map +1 -0
  163. package/dist/adt/table-query.d.ts +4 -2
  164. package/dist/adt/table-query.d.ts.map +1 -1
  165. package/dist/adt/table-query.js +37 -10
  166. package/dist/adt/table-query.js.map +1 -1
  167. package/dist/adt/table-settings.d.ts +67 -0
  168. package/dist/adt/table-settings.d.ts.map +1 -0
  169. package/dist/adt/table-settings.js +207 -0
  170. package/dist/adt/table-settings.js.map +1 -0
  171. package/dist/adt/text-elements.d.ts +7 -1
  172. package/dist/adt/text-elements.d.ts.map +1 -1
  173. package/dist/adt/text-elements.js +67 -25
  174. package/dist/adt/text-elements.js.map +1 -1
  175. package/dist/adt/text-part-changes.d.ts +4 -0
  176. package/dist/adt/text-part-changes.d.ts.map +1 -0
  177. package/dist/adt/text-part-changes.js +43 -0
  178. package/dist/adt/text-part-changes.js.map +1 -0
  179. package/dist/adt/transport-diff.d.ts +16 -25
  180. package/dist/adt/transport-diff.d.ts.map +1 -1
  181. package/dist/adt/transport-diff.js +201 -103
  182. package/dist/adt/transport-diff.js.map +1 -1
  183. package/dist/adt/transport-review-budget.d.ts +15 -0
  184. package/dist/adt/transport-review-budget.d.ts.map +1 -0
  185. package/dist/adt/transport-review-budget.js +57 -0
  186. package/dist/adt/transport-review-budget.js.map +1 -0
  187. package/dist/adt/transport.d.ts +1 -1
  188. package/dist/adt/transport.d.ts.map +1 -1
  189. package/dist/adt/transport.js +4 -3
  190. package/dist/adt/transport.js.map +1 -1
  191. package/dist/adt/types.d.ts +10 -4
  192. package/dist/adt/types.d.ts.map +1 -1
  193. package/dist/adt/user-agent.d.ts +1 -1
  194. package/dist/adt/where-used-native.d.ts +22 -0
  195. package/dist/adt/where-used-native.d.ts.map +1 -0
  196. package/dist/adt/where-used-native.js +111 -0
  197. package/dist/adt/where-used-native.js.map +1 -0
  198. package/dist/adt/xml-parser.d.ts +6 -36
  199. package/dist/adt/xml-parser.d.ts.map +1 -1
  200. package/dist/adt/xml-parser.js +28 -235
  201. package/dist/adt/xml-parser.js.map +1 -1
  202. package/dist/aff/validator.d.ts.map +1 -1
  203. package/dist/aff/validator.js +8 -2
  204. package/dist/aff/validator.js.map +1 -1
  205. package/dist/authz/policy.d.ts.map +1 -1
  206. package/dist/authz/policy.js +10 -2
  207. package/dist/authz/policy.js.map +1 -1
  208. package/dist/cache/sqlite-driver.d.ts +24 -0
  209. package/dist/cache/sqlite-driver.d.ts.map +1 -0
  210. package/dist/cache/sqlite-driver.js +59 -0
  211. package/dist/cache/sqlite-driver.js.map +1 -0
  212. package/dist/cache/sqlite.d.ts +4 -2
  213. package/dist/cache/sqlite.d.ts.map +1 -1
  214. package/dist/cache/sqlite.js +5 -4
  215. package/dist/cache/sqlite.js.map +1 -1
  216. package/dist/cli.js +4 -1
  217. package/dist/cli.js.map +1 -1
  218. package/dist/context/grep.d.ts +2 -0
  219. package/dist/context/grep.d.ts.map +1 -1
  220. package/dist/context/grep.js +8 -7
  221. package/dist/context/grep.js.map +1 -1
  222. package/dist/context/line-range.d.ts +6 -0
  223. package/dist/context/line-range.d.ts.map +1 -0
  224. package/dist/context/line-range.js +23 -0
  225. package/dist/context/line-range.js.map +1 -0
  226. package/dist/extract-sap-cookies.js +1 -0
  227. package/dist/extract-sap-cookies.js.map +1 -1
  228. package/dist/handlers/activate.d.ts.map +1 -1
  229. package/dist/handlers/activate.js +69 -7
  230. package/dist/handlers/activate.js.map +1 -1
  231. package/dist/handlers/activation-results.d.ts.map +1 -1
  232. package/dist/handlers/activation-results.js +9 -1
  233. package/dist/handlers/activation-results.js.map +1 -1
  234. package/dist/handlers/api-release-fields.d.ts +23 -0
  235. package/dist/handlers/api-release-fields.d.ts.map +1 -0
  236. package/dist/handlers/api-release-fields.js +21 -0
  237. package/dist/handlers/api-release-fields.js.map +1 -0
  238. package/dist/handlers/application-log-input.d.ts +32 -0
  239. package/dist/handlers/application-log-input.d.ts.map +1 -0
  240. package/dist/handlers/application-log-input.js +34 -0
  241. package/dist/handlers/application-log-input.js.map +1 -0
  242. package/dist/handlers/application-log.d.ts +4 -0
  243. package/dist/handlers/application-log.d.ts.map +1 -0
  244. package/dist/handlers/application-log.js +14 -0
  245. package/dist/handlers/application-log.js.map +1 -0
  246. package/dist/handlers/cds-hints.d.ts +2 -2
  247. package/dist/handlers/cds-hints.d.ts.map +1 -1
  248. package/dist/handlers/cds-hints.js +21 -63
  249. package/dist/handlers/cds-hints.js.map +1 -1
  250. package/dist/handlers/context.d.ts.map +1 -1
  251. package/dist/handlers/context.js +7 -3
  252. package/dist/handlers/context.js.map +1 -1
  253. package/dist/handlers/diagnose.d.ts.map +1 -1
  254. package/dist/handlers/diagnose.js +10 -1
  255. package/dist/handlers/diagnose.js.map +1 -1
  256. package/dist/handlers/dispatch.d.ts.map +1 -1
  257. package/dist/handlers/dispatch.js +54 -9
  258. package/dist/handlers/dispatch.js.map +1 -1
  259. package/dist/handlers/dump-filter-inputs.d.ts +38 -0
  260. package/dist/handlers/dump-filter-inputs.d.ts.map +1 -0
  261. package/dist/handlers/dump-filter-inputs.js +44 -0
  262. package/dist/handlers/dump-filter-inputs.js.map +1 -0
  263. package/dist/handlers/expanded-read.d.ts +24 -0
  264. package/dist/handlers/expanded-read.d.ts.map +1 -0
  265. package/dist/handlers/expanded-read.js +56 -0
  266. package/dist/handlers/expanded-read.js.map +1 -0
  267. package/dist/handlers/feature-cache.d.ts +11 -3
  268. package/dist/handlers/feature-cache.d.ts.map +1 -1
  269. package/dist/handlers/feature-cache.js +57 -3
  270. package/dist/handlers/feature-cache.js.map +1 -1
  271. package/dist/handlers/function-parameter-language.d.ts +5 -0
  272. package/dist/handlers/function-parameter-language.d.ts.map +1 -0
  273. package/dist/handlers/function-parameter-language.js +19 -0
  274. package/dist/handlers/function-parameter-language.js.map +1 -0
  275. package/dist/handlers/function-processing.d.ts +5 -0
  276. package/dist/handlers/function-processing.d.ts.map +1 -1
  277. package/dist/handlers/function-processing.js +5 -0
  278. package/dist/handlers/function-processing.js.map +1 -1
  279. package/dist/handlers/hyperfocused.d.ts +1 -1
  280. package/dist/handlers/hyperfocused.d.ts.map +1 -1
  281. package/dist/handlers/hyperfocused.js +2 -1
  282. package/dist/handlers/hyperfocused.js.map +1 -1
  283. package/dist/handlers/long-text-input.d.ts +113 -0
  284. package/dist/handlers/long-text-input.d.ts.map +1 -0
  285. package/dist/handlers/long-text-input.js +113 -0
  286. package/dist/handlers/long-text-input.js.map +1 -0
  287. package/dist/handlers/long-text.d.ts +5 -0
  288. package/dist/handlers/long-text.d.ts.map +1 -0
  289. package/dist/handlers/long-text.js +122 -0
  290. package/dist/handlers/long-text.js.map +1 -0
  291. package/dist/handlers/manage.d.ts.map +1 -1
  292. package/dist/handlers/manage.js +7 -23
  293. package/dist/handlers/manage.js.map +1 -1
  294. package/dist/handlers/navigate.d.ts.map +1 -1
  295. package/dist/handlers/navigate.js +8 -3
  296. package/dist/handlers/navigate.js.map +1 -1
  297. package/dist/handlers/object-types.d.ts.map +1 -1
  298. package/dist/handlers/object-types.js +31 -7
  299. package/dist/handlers/object-types.js.map +1 -1
  300. package/dist/handlers/query-input.d.ts +50 -0
  301. package/dist/handlers/query-input.d.ts.map +1 -0
  302. package/dist/handlers/query-input.js +59 -0
  303. package/dist/handlers/query-input.js.map +1 -0
  304. package/dist/handlers/query-tool.d.ts +11 -0
  305. package/dist/handlers/query-tool.d.ts.map +1 -0
  306. package/dist/handlers/query-tool.js +99 -0
  307. package/dist/handlers/query-tool.js.map +1 -0
  308. package/dist/handlers/query.d.ts +1 -1
  309. package/dist/handlers/query.d.ts.map +1 -1
  310. package/dist/handlers/query.js +7 -1
  311. package/dist/handlers/query.js.map +1 -1
  312. package/dist/handlers/read.d.ts +1 -0
  313. package/dist/handlers/read.d.ts.map +1 -1
  314. package/dist/handlers/read.js +119 -14
  315. package/dist/handlers/read.js.map +1 -1
  316. package/dist/handlers/schemas.d.ts +57 -4
  317. package/dist/handlers/schemas.d.ts.map +1 -1
  318. package/dist/handlers/schemas.js +140 -17
  319. package/dist/handlers/schemas.js.map +1 -1
  320. package/dist/handlers/search.d.ts.map +1 -1
  321. package/dist/handlers/search.js +10 -6
  322. package/dist/handlers/search.js.map +1 -1
  323. package/dist/handlers/syntax.d.ts.map +1 -1
  324. package/dist/handlers/syntax.js +8 -0
  325. package/dist/handlers/syntax.js.map +1 -1
  326. package/dist/handlers/table-type-fields.d.ts +33 -0
  327. package/dist/handlers/table-type-fields.d.ts.map +1 -0
  328. package/dist/handlers/table-type-fields.js +22 -0
  329. package/dist/handlers/table-type-fields.js.map +1 -0
  330. package/dist/handlers/tool-descriptions.d.ts.map +1 -1
  331. package/dist/handlers/tool-descriptions.js +8 -3
  332. package/dist/handlers/tool-descriptions.js.map +1 -1
  333. package/dist/handlers/tool-registry.d.ts +5 -5
  334. package/dist/handlers/tool-registry.d.ts.map +1 -1
  335. package/dist/handlers/tool-registry.js +10 -7
  336. package/dist/handlers/tool-registry.js.map +1 -1
  337. package/dist/handlers/tools.d.ts +1 -1
  338. package/dist/handlers/tools.d.ts.map +1 -1
  339. package/dist/handlers/tools.js +99 -101
  340. package/dist/handlers/tools.js.map +1 -1
  341. package/dist/handlers/transport-review.d.ts +5 -0
  342. package/dist/handlers/transport-review.d.ts.map +1 -0
  343. package/dist/handlers/transport-review.js +108 -0
  344. package/dist/handlers/transport-review.js.map +1 -0
  345. package/dist/handlers/transport.d.ts.map +1 -1
  346. package/dist/handlers/transport.js +3 -58
  347. package/dist/handlers/transport.js.map +1 -1
  348. package/dist/handlers/where-used-details.d.ts +28 -0
  349. package/dist/handlers/where-used-details.d.ts.map +1 -0
  350. package/dist/handlers/where-used-details.js +67 -0
  351. package/dist/handlers/where-used-details.js.map +1 -0
  352. package/dist/handlers/where-used.d.ts +8 -3
  353. package/dist/handlers/where-used.d.ts.map +1 -1
  354. package/dist/handlers/where-used.js +40 -18
  355. package/dist/handlers/where-used.js.map +1 -1
  356. package/dist/handlers/write/create.d.ts.map +1 -1
  357. package/dist/handlers/write/create.js +69 -27
  358. package/dist/handlers/write/create.js.map +1 -1
  359. package/dist/handlers/write/rap.d.ts.map +1 -1
  360. package/dist/handlers/write/rap.js +2 -4
  361. package/dist/handlers/write/rap.js.map +1 -1
  362. package/dist/handlers/write/table-settings.d.ts +5 -0
  363. package/dist/handlers/write/table-settings.d.ts.map +1 -0
  364. package/dist/handlers/write/table-settings.js +27 -0
  365. package/dist/handlers/write/table-settings.js.map +1 -0
  366. package/dist/handlers/write/update-delete.d.ts +1 -1
  367. package/dist/handlers/write/update-delete.d.ts.map +1 -1
  368. package/dist/handlers/write/update-delete.js +32 -12
  369. package/dist/handlers/write/update-delete.js.map +1 -1
  370. package/dist/handlers/write-helpers.d.ts +4 -1
  371. package/dist/handlers/write-helpers.d.ts.map +1 -1
  372. package/dist/handlers/write-helpers.js +68 -8
  373. package/dist/handlers/write-helpers.js.map +1 -1
  374. package/dist/handlers/write.d.ts.map +1 -1
  375. package/dist/handlers/write.js +6 -10
  376. package/dist/handlers/write.js.map +1 -1
  377. package/dist/server/audit.d.ts +4 -0
  378. package/dist/server/audit.d.ts.map +1 -1
  379. package/dist/server/audit.js +49 -2
  380. package/dist/server/audit.js.map +1 -1
  381. package/dist/server/config.d.ts.map +1 -1
  382. package/dist/server/config.js +43 -2
  383. package/dist/server/config.js.map +1 -1
  384. package/dist/server/destination-discovery.d.ts +12 -2
  385. package/dist/server/destination-discovery.d.ts.map +1 -1
  386. package/dist/server/destination-discovery.js +33 -7
  387. package/dist/server/destination-discovery.js.map +1 -1
  388. package/dist/server/destination-registry.d.ts +10 -6
  389. package/dist/server/destination-registry.d.ts.map +1 -1
  390. package/dist/server/destination-registry.js +38 -15
  391. package/dist/server/destination-registry.js.map +1 -1
  392. package/dist/server/http-request-body.d.ts +4 -0
  393. package/dist/server/http-request-body.d.ts.map +1 -0
  394. package/dist/server/http-request-body.js +65 -0
  395. package/dist/server/http-request-body.js.map +1 -0
  396. package/dist/server/http.d.ts +5 -2
  397. package/dist/server/http.d.ts.map +1 -1
  398. package/dist/server/http.js +71 -9
  399. package/dist/server/http.js.map +1 -1
  400. package/dist/server/multi-target-authorization-audit.d.ts +5 -0
  401. package/dist/server/multi-target-authorization-audit.d.ts.map +1 -0
  402. package/dist/server/multi-target-authorization-audit.js +18 -0
  403. package/dist/server/multi-target-authorization-audit.js.map +1 -0
  404. package/dist/server/multi-target-authorization-startup.d.ts +8 -0
  405. package/dist/server/multi-target-authorization-startup.d.ts.map +1 -0
  406. package/dist/server/multi-target-authorization-startup.js +38 -0
  407. package/dist/server/multi-target-authorization-startup.js.map +1 -0
  408. package/dist/server/multi-target-authorization.d.ts +29 -0
  409. package/dist/server/multi-target-authorization.d.ts.map +1 -0
  410. package/dist/server/multi-target-authorization.js +97 -0
  411. package/dist/server/multi-target-authorization.js.map +1 -0
  412. package/dist/server/multi-target-bearer-auth.d.ts +5 -0
  413. package/dist/server/multi-target-bearer-auth.d.ts.map +1 -0
  414. package/dist/server/multi-target-bearer-auth.js +39 -0
  415. package/dist/server/multi-target-bearer-auth.js.map +1 -0
  416. package/dist/server/multi-target-catalog-enforced.d.ts +29 -0
  417. package/dist/server/multi-target-catalog-enforced.d.ts.map +1 -0
  418. package/dist/server/multi-target-catalog-enforced.js +142 -0
  419. package/dist/server/multi-target-catalog-enforced.js.map +1 -0
  420. package/dist/server/multi-target-catalog-projection.d.ts +7 -0
  421. package/dist/server/multi-target-catalog-projection.d.ts.map +1 -0
  422. package/dist/server/multi-target-catalog-projection.js +52 -0
  423. package/dist/server/multi-target-catalog-projection.js.map +1 -0
  424. package/dist/server/multi-target-feature-state.d.ts +0 -2
  425. package/dist/server/multi-target-feature-state.d.ts.map +1 -1
  426. package/dist/server/multi-target-feature-state.js +0 -19
  427. package/dist/server/multi-target-feature-state.js.map +1 -1
  428. package/dist/server/multi-target-identity.d.ts +3 -0
  429. package/dist/server/multi-target-identity.d.ts.map +1 -1
  430. package/dist/server/multi-target-identity.js +9 -0
  431. package/dist/server/multi-target-identity.js.map +1 -1
  432. package/dist/server/multi-target-request-projection.d.ts +14 -0
  433. package/dist/server/multi-target-request-projection.d.ts.map +1 -0
  434. package/dist/server/multi-target-request-projection.js +16 -0
  435. package/dist/server/multi-target-request-projection.js.map +1 -0
  436. package/dist/server/multi-target-runtime.d.ts.map +1 -1
  437. package/dist/server/multi-target-runtime.js +1 -0
  438. package/dist/server/multi-target-runtime.js.map +1 -1
  439. package/dist/server/multi-target-server.d.ts +4 -1
  440. package/dist/server/multi-target-server.d.ts.map +1 -1
  441. package/dist/server/multi-target-server.js +111 -11
  442. package/dist/server/multi-target-server.js.map +1 -1
  443. package/dist/server/multi-target-tools.d.ts +1 -1
  444. package/dist/server/multi-target-tools.d.ts.map +1 -1
  445. package/dist/server/multi-target-tools.js +22 -15
  446. package/dist/server/multi-target-tools.js.map +1 -1
  447. package/dist/server/private-mcp-response.d.ts +4 -0
  448. package/dist/server/private-mcp-response.d.ts.map +1 -0
  449. package/dist/server/private-mcp-response.js +14 -0
  450. package/dist/server/private-mcp-response.js.map +1 -0
  451. package/dist/server/server-cache.d.ts +5 -0
  452. package/dist/server/server-cache.d.ts.map +1 -0
  453. package/dist/server/server-cache.js +30 -0
  454. package/dist/server/server-cache.js.map +1 -0
  455. package/dist/server/server.d.ts +7 -21
  456. package/dist/server/server.d.ts.map +1 -1
  457. package/dist/server/server.js +60 -89
  458. package/dist/server/server.js.map +1 -1
  459. package/dist/server/sinks/btp-auditlog.d.ts.map +1 -1
  460. package/dist/server/sinks/btp-auditlog.js +4 -1
  461. package/dist/server/sinks/btp-auditlog.js.map +1 -1
  462. package/dist/server/tool-auth.d.ts +1 -1
  463. package/dist/server/tool-auth.d.ts.map +1 -1
  464. package/dist/server/tool-auth.js +24 -4
  465. package/dist/server/tool-auth.js.map +1 -1
  466. package/dist/server/types.d.ts +7 -0
  467. package/dist/server/types.d.ts.map +1 -1
  468. package/dist/server/types.js +4 -0
  469. package/dist/server/types.js.map +1 -1
  470. package/dist/version.d.ts +1 -1
  471. package/dist/version.js +1 -1
  472. package/package.json +21 -13
package/dist/adt/http.js CHANGED
@@ -9,15 +9,19 @@ import { Agent, Client } from 'undici';
9
9
  import { getCurrentContext } from '../server/context.js';
10
10
  import { logger } from '../server/logger.js';
11
11
  import { traceHeaders } from '../server/trace-context.js';
12
+ import { acceptFallback } from './accept-fallback.js';
12
13
  import { connectivityProxyResponse, prepareBoundedResponse } from './bounded-response.js';
13
14
  import { resolveCookies } from './cookies.js';
14
15
  import { resolveAcceptType, resolveContentType } from './discovery.js';
15
16
  import { AdtApiError, AdtNetworkError, AdtResponseLimitError } from './errors.js';
16
17
  import { awaitWithinRequestBudget, requestBudgetSignal, requestSignal, sleepWithinRequestBudget, throwIfRequestCancelled, withoutResponseBudget, } from './http-deadline.js';
18
+ import { parseRetryAfter } from './http-retry-after.js';
17
19
  import { prepareDataPreviewWireBody } from './http-wire-body.js';
18
- import { legacyContentHandlerFallback } from './legacy-content-handler.js';
20
+ import { legacyContentHandlerFallback, rejectEmptyAdtHtmlResponse } from './legacy-content-handler.js';
19
21
  import { fetchWithAttemptBudget } from './request-attempt-budget.js';
22
+ import { hasSecuritySessionCookie, SecuritySessionGate } from './security-session-gate.js';
20
23
  import { resolveSapUserAgent } from './user-agent.js';
24
+ export { parseRetryAfter } from './http-retry-after.js';
21
25
  /**
22
26
  * Opt-in wire-level debug logging.
23
27
  *
@@ -103,6 +107,8 @@ export class AdtHttpClient {
103
107
  dbRetryInProgress = false;
104
108
  /** Set after a 401 clears stale cookies — triggers file reload on the next request */
105
109
  cookiesCleared = false;
110
+ /** Keeps a cold client at one SAP security session (see security-session-gate.ts). */
111
+ securitySessionGate = new SecuritySessionGate();
106
112
  /** Shared by stateful clones so one rejected Basic credential cannot fan out internally. */
107
113
  authenticationAttemptState;
108
114
  constructor(config, authenticationAttemptState) {
@@ -235,6 +241,8 @@ export class AdtHttpClient {
235
241
  }
236
242
  if (!options?.signal && options?.deadline === undefined)
237
243
  throw error;
244
+ if (options?.signal?.aborted)
245
+ throwIfRequestCancelled(options);
238
246
  const cause = error instanceof Error ? error : new Error(String(error));
239
247
  throw new AdtNetworkError(cause.message, cause);
240
248
  }
@@ -273,6 +281,7 @@ export class AdtHttpClient {
273
281
  /** Inner request method — CSRF, retries, content negotiation */
274
282
  async requestInner(method, path, body, contentType, extraHeaders, options) {
275
283
  throwIfRequestCancelled(options);
284
+ const expectBody = method !== 'HEAD';
276
285
  // Auto-fetch CSRF token for modifying requests
277
286
  if (isModifyingMethod(method) && !this.csrfToken) {
278
287
  await this.fetchCsrfToken(withoutResponseBudget(options));
@@ -350,7 +359,16 @@ export class AdtHttpClient {
350
359
  if (this.config.sapConnectivityAuth && !this.config.ppProxyAuth) {
351
360
  headers['SAP-Connectivity-Authentication'] = this.config.sapConnectivityAuth;
352
361
  }
353
- const url = this.buildUrl(path);
362
+ // Quick-fix lookup includes queries (#993); old revision feeds append source paths to them. Use context headers.
363
+ const sapContextInHeaders = (method === 'POST' && path.startsWith('/sap/bc/adt/quickfixes/proposals/')) ||
364
+ (method === 'GET' && /^\/sap\/bc\/adt\/[^?#]+\/versions$/.test(path));
365
+ if (sapContextInHeaders) {
366
+ if (this.config.client)
367
+ headers['sap-client'] = this.config.client;
368
+ if (this.config.language)
369
+ headers['sap-language'] = this.config.language;
370
+ }
371
+ const url = this.buildUrl(path, sapContextInHeaders);
354
372
  const httpStart = Date.now();
355
373
  // Per-request guards to prevent infinite retry loops
356
374
  const retryTransientErrors = options?.retryTransientErrors !== false;
@@ -358,10 +376,8 @@ export class AdtHttpClient {
358
376
  let authRetried = false;
359
377
  let retried429 = false;
360
378
  try {
361
- let response = await this.doFetch(url, method, headers, wireBody, options);
379
+ let response = await this.doFetch(url, method, headers, wireBody, options, this.config.retryUnauthorized !== false);
362
380
  let responseBody = await response.text();
363
- // Persist any Set-Cookie headers from the response
364
- this.storeCookies(response);
365
381
  // Detect broken DB connection on the assigned work process.
366
382
  // SAP's ICM routes all requests with the same session cookie to the same
367
383
  // work process. If that WP has a broken HANA connection, every request fails
@@ -403,8 +419,7 @@ export class AdtHttpClient {
403
419
  }
404
420
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
405
421
  const retryBody = await retryResp.text();
406
- this.storeCookies(retryResp);
407
- const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path);
422
+ const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
408
423
  logger.emitAudit({
409
424
  timestamp: new Date().toISOString(),
410
425
  level: 'info',
@@ -437,9 +452,9 @@ export class AdtHttpClient {
437
452
  errorBody: `503 Service Unavailable — retrying in ${Math.round(jitterMs)}ms (${source})`,
438
453
  });
439
454
  await sleepWithinRequestBudget(jitterMs, options);
455
+ this.refreshSessionHeaders(method, headers);
440
456
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
441
457
  const retryBody = await retryResp.text();
442
- this.storeCookies(retryResp);
443
458
  logger.emitAudit({
444
459
  timestamp: new Date().toISOString(),
445
460
  level: retryResp.status === 503 ? 'warn' : 'info',
@@ -450,7 +465,7 @@ export class AdtHttpClient {
450
465
  durationMs: Date.now() - httpStart,
451
466
  errorBody: `503 retry completed (${retryResp.status})`,
452
467
  });
453
- return this.handleResponse(retryResp.status, retryResp.headers, retryBody, path);
468
+ return this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
454
469
  }
455
470
  // Handle 429 Too Many Requests — emitted by SAP Web Dispatcher, BTP API
456
471
  // Management, or any upstream gateway throttling us. Honors Retry-After when present;
@@ -469,9 +484,9 @@ export class AdtHttpClient {
469
484
  errorBody: `429 Too Many Requests — retrying in ${Math.round(jitterMs)}ms (${source})`,
470
485
  });
471
486
  await sleepWithinRequestBudget(jitterMs, options);
487
+ this.refreshSessionHeaders(method, headers);
472
488
  const retryResp = await this.doFetch(url, method, headers, wireBody, options);
473
489
  const retryBody = await retryResp.text();
474
- this.storeCookies(retryResp);
475
490
  logger.emitAudit({
476
491
  timestamp: new Date().toISOString(),
477
492
  level: retryResp.status === 429 ? 'warn' : 'info',
@@ -482,7 +497,7 @@ export class AdtHttpClient {
482
497
  durationMs: Date.now() - httpStart,
483
498
  errorBody: `429 retry completed (${retryResp.status})`,
484
499
  });
485
- return this.handleResponse(retryResp.status, retryResp.headers, retryBody, path);
500
+ return this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
486
501
  }
487
502
  // Handle 401 session timeout — reset session and retry once.
488
503
  // Uses per-request guard (not instance-level) so concurrent requests each get their own retry.
@@ -500,8 +515,6 @@ export class AdtHttpClient {
500
515
  durationMs: Date.now() - httpStart,
501
516
  errorBody: '401 session expired — resetting session and retrying',
502
517
  });
503
- // Clear session to force fresh authentication
504
- this.resetSession();
505
518
  // Pick up an out-of-band rotated cookie file so the call that observes the
506
519
  // expiry can recover; the lazy `cookiesCleared` reload stays the fallback.
507
520
  // `cookieFile`, not `isCookieAuthMode()` — cookieString has nothing to re-read,
@@ -531,7 +544,6 @@ export class AdtHttpClient {
531
544
  }
532
545
  response = await this.doFetch(url, method, headers, wireBody, options);
533
546
  responseBody = await response.text();
534
- this.storeCookies(response);
535
547
  logger.emitAudit({
536
548
  timestamp: new Date().toISOString(),
537
549
  level: 'info',
@@ -560,20 +572,9 @@ export class AdtHttpClient {
560
572
  if (csrfRefreshedCookieHeader) {
561
573
  headers.Cookie = csrfRefreshedCookieHeader;
562
574
  }
563
- const retryResponse = await this.doFetch(url, method, headers, wireBody, options);
564
- const retryBody = await retryResponse.text();
565
- this.storeCookies(retryResponse);
566
- const result = this.handleResponse(retryResponse.status, retryResponse.headers, retryBody, path);
567
- logger.emitAudit({
568
- timestamp: new Date().toISOString(),
569
- level: 'info',
570
- event: 'http_request',
571
- method,
572
- path,
573
- statusCode: retryResponse.status,
574
- durationMs: Date.now() - httpStart,
575
- });
576
- return result;
575
+ response = await this.doFetch(url, method, headers, wireBody, options);
576
+ responseBody = await response.text();
577
+ // A refreshed session can still need legacy content negotiation below (#996).
577
578
  }
578
579
  // Retry negotiation once, including the narrowly matched NW 7.40 handler error.
579
580
  const legacyFallback = legacyContentHandlerFallback(response.status, responseBody, method, negotiationKey, headers);
@@ -586,25 +587,11 @@ export class AdtHttpClient {
586
587
  headersChanged = true;
587
588
  }
588
589
  else if (response.status === 406) {
589
- // Server rejected our Accept header — try fallback
590
- const inferred = inferAcceptFromError(responseBody);
591
- if (inferred && inferred !== fallbackHeaders.Accept) {
592
- fallbackHeaders.Accept = inferred;
590
+ const fallback = acceptFallback(responseBody, fallbackHeaders.Accept, method, negotiationKey);
591
+ if (fallback) {
592
+ fallbackHeaders.Accept = fallback;
593
593
  headersChanged = true;
594
594
  }
595
- else if (fallbackHeaders.Accept &&
596
- fallbackHeaders.Accept !== '*/*' &&
597
- fallbackHeaders.Accept !== 'application/xml') {
598
- // Fall back to generic XML first
599
- fallbackHeaders.Accept = 'application/xml';
600
- headersChanged = true;
601
- }
602
- else if (fallbackHeaders.Accept === 'application/xml') {
603
- // application/xml was already rejected — fall back to wildcard
604
- fallbackHeaders.Accept = '*/*';
605
- headersChanged = true;
606
- }
607
- // If Accept is already */* and no inferred type, no useful fallback — skip retry
608
595
  }
609
596
  else {
610
597
  // 415: Server rejected our Content-Type — try fallbacks:
@@ -634,15 +621,10 @@ export class AdtHttpClient {
634
621
  durationMs: Date.now() - httpStart,
635
622
  errorBody: `Content negotiation ${response.status} — retrying with fallback headers`,
636
623
  });
624
+ this.refreshSessionHeaders(method, fallbackHeaders);
637
625
  const retryResp = await this.doFetch(url, method, fallbackHeaders, wireBody, options);
638
626
  const retryBody = await retryResp.text();
639
- this.storeCookies(retryResp);
640
- // Store CSRF token from retry response
641
- const retryToken = retryResp.headers.get('x-csrf-token');
642
- if (retryToken && retryToken !== 'Required') {
643
- this.csrfToken = retryToken;
644
- }
645
- const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path);
627
+ const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path, expectBody);
646
628
  const currentContentType = contentType ?? headers['Content-Type'];
647
629
  const negotiated = {};
648
630
  if (retryAccept !== headers.Accept) {
@@ -669,12 +651,7 @@ export class AdtHttpClient {
669
651
  }
670
652
  // No meaningful header change — fall through to normal error handling
671
653
  }
672
- // Store CSRF token from response
673
- const responseToken = response.headers.get('x-csrf-token');
674
- if (responseToken && responseToken !== 'Required') {
675
- this.csrfToken = responseToken;
676
- }
677
- const result = this.handleResponse(response.status, response.headers, responseBody, path);
654
+ const result = this.handleResponse(response.status, response.headers, responseBody, path, expectBody);
678
655
  logger.emitAudit({
679
656
  timestamp: new Date().toISOString(),
680
657
  level: 'debug',
@@ -724,6 +701,8 @@ export class AdtHttpClient {
724
701
  }
725
702
  if (err instanceof AdtNetworkError || err instanceof AdtResponseLimitError)
726
703
  throw err;
704
+ if (options?.signal?.aborted)
705
+ throwIfRequestCancelled(options);
727
706
  const message = err instanceof Error ? err.message : String(err);
728
707
  throw new AdtNetworkError(message, err instanceof Error ? err : undefined);
729
708
  }
@@ -762,7 +741,7 @@ export class AdtHttpClient {
762
741
  }
763
742
  }
764
743
  /** Handle response: throw on error status, return normalized response */
765
- handleResponse(status, headers, body, path) {
744
+ handleResponse(status, headers, body, path, expectBody = true) {
766
745
  const contentType = headers.get('content-type')?.toLowerCase();
767
746
  const isDiscovery = ['/sap/bc/adt/core/discovery', '/sap/bc/adt/discovery'].includes(path.split('?', 1)[0]);
768
747
  if (status === 200 &&
@@ -775,6 +754,8 @@ export class AdtHttpClient {
775
754
  this.notifyUnauthorized(path);
776
755
  throw new AdtApiError('ADT call returned HTML login page — authentication required. If using cookies, they may have expired. If using Basic auth, credentials may be invalid or not authorized for ADT (S_ADT_RES missing). If on an SSO-only system, try SAP_DISABLE_SAML=true or see docs/enterprise-auth.md. Re-run arc-1 after fixing.', 401, path, body.slice(0, 500));
777
756
  }
757
+ if (expectBody)
758
+ rejectEmptyAdtHtmlResponse(status, contentType, body, path);
778
759
  if (status >= 400) {
779
760
  if (status === 401) {
780
761
  this.notifyUnauthorized(path);
@@ -829,12 +810,6 @@ export class AdtHttpClient {
829
810
  if (this.cookiesCleared && this.isCookieAuthMode()) {
830
811
  this.reloadCookiesFromSource();
831
812
  }
832
- // A token only counts as proof when the response itself succeeded: SAP returns one on
833
- // failures too, and the old code accepted a token from a 401 — masking the auth error.
834
- const usableToken = (response) => {
835
- const token = response.headers.get('x-csrf-token')?.trim();
836
- return response.ok && token && token.toLowerCase() !== 'required' ? token : undefined;
837
- };
838
813
  // Every probe keeps the same identity, current cookies and caller's request budget.
839
814
  const probe = async (method) => {
840
815
  const cookieHeader = this.composeCookieHeader();
@@ -844,7 +819,6 @@ export class AdtHttpClient {
844
819
  delete headers.Cookie;
845
820
  const started = Date.now();
846
821
  const response = await this.doFetch(this.buildUrl(path), method, headers, undefined, options);
847
- this.storeCookies(response);
848
822
  logger.emitAudit({
849
823
  timestamp: new Date().toISOString(),
850
824
  level: 'debug',
@@ -853,13 +827,13 @@ export class AdtHttpClient {
853
827
  path,
854
828
  statusCode: response.status,
855
829
  durationMs: Date.now() - started,
856
- success: !!usableToken(response),
857
- adtMode: this.config.sessionType ?? 'unspecified',
858
- hasContext: /(?:^|;\s*)sap-contextid=/.test(cookieHeader ?? ''),
830
+ success: !!usableCsrfToken(response),
831
+ adtMode: headers['X-sap-adt-sessiontype'] === undefined ? 'unspecified' : (this.config.sessionType ?? 'unspecified'),
832
+ hasContext: /(?:^|;\s*)sap-contextid=/.test(headers.Cookie ?? ''),
859
833
  });
860
- if (method === 'GET' && response.status === 200 && !usableToken(response)) {
861
- // Preserve the login-page check even when an old handler reports HTTP 200.
862
- this.handleResponse(response.status, response.headers, await response.text(), path);
834
+ if (method === 'GET' && response.status === 200 && !usableCsrfToken(response)) {
835
+ // Check login pages, but preserve the header-only legacy discovery fallback.
836
+ this.handleResponse(response.status, response.headers, await response.text(), path, false);
863
837
  }
864
838
  // Only headers are needed; release GET bodies before a fallback or return.
865
839
  if (!response.bodyUsed)
@@ -888,16 +862,23 @@ export class AdtHttpClient {
888
862
  // The tested 7.50/7.58/8.16 systems returned HEAD 400 with a token; GET returned 200.
889
863
  // Retry these HEAD refusals or a successful response without a token on the same path.
890
864
  // A successful HEAD with a usable token remains the one-request fast path.
891
- if ([400, 403, 405].includes(response.status) || (response.ok && !usableToken(response))) {
865
+ const headStatus = response.status;
866
+ if ([400, 403, 405].includes(response.status) || (response.ok && !usableCsrfToken(response))) {
867
+ response = await probe('GET');
868
+ }
869
+ // Both stateful discovery probes can fail on affected routes (#1044). Bootstrap once
870
+ // without that header; keep identity/cookies and subsequent lock/write requests stateful.
871
+ if (this.config.sessionType === 'stateful' && headStatus === 400 && response.status === 400) {
872
+ delete headers['X-sap-adt-sessiontype'];
892
873
  response = await probe('GET');
893
874
  }
894
875
  // Older ADT handlers may return an empty 200 for a missing core resource (#817).
895
876
  // A real auth/server failure must not be hidden by trying another endpoint.
896
- if (response.status === 404 || response.status === 405 || (response.ok && !usableToken(response))) {
877
+ if (response.status === 404 || response.status === 405 || (response.ok && !usableCsrfToken(response))) {
897
878
  path = '/sap/bc/adt/discovery';
898
879
  response = await probe('GET');
899
880
  }
900
- const token = usableToken(response);
881
+ const token = usableCsrfToken(response);
901
882
  if (!token) {
902
883
  if (response.status === 401) {
903
884
  if (this.isCookieAuthMode())
@@ -910,12 +891,13 @@ export class AdtHttpClient {
910
891
  }
911
892
  throw new AdtApiError(`No CSRF token in response (HTTP ${response.status})`, response.status, path);
912
893
  }
913
- this.csrfToken = token;
914
894
  return path;
915
895
  }
916
896
  catch (err) {
917
897
  if (err instanceof AdtApiError || err instanceof AdtNetworkError)
918
898
  throw err;
899
+ if (options?.signal?.aborted)
900
+ throwIfRequestCancelled(options);
919
901
  const message = err instanceof Error ? err.message : String(err);
920
902
  throw new AdtNetworkError(`CSRF token fetch failed: ${message}`, err instanceof Error ? err : undefined);
921
903
  }
@@ -954,8 +936,7 @@ export class AdtHttpClient {
954
936
  */
955
937
  clearCookiesAndMark() {
956
938
  this.config.cookies = {};
957
- this.cookieJar.clear();
958
- this.csrfToken = '';
939
+ this.resetSession();
959
940
  this.cookiesCleared = true;
960
941
  }
961
942
  /**
@@ -1004,6 +985,7 @@ export class AdtHttpClient {
1004
985
  resetSession() {
1005
986
  this.cookieJar.clear();
1006
987
  this.csrfToken = '';
988
+ this.securitySessionGate.reset();
1007
989
  }
1008
990
  /**
1009
991
  * Build the `Cookie` request header by merging the static `config.cookies`
@@ -1036,11 +1018,18 @@ export class AdtHttpClient {
1036
1018
  return undefined;
1037
1019
  return Array.from(merged, ([name, value]) => `${name}=${value}`).join('; ');
1038
1020
  }
1021
+ /** Read the current pair together after a wait or a response that can rotate the session. */
1022
+ refreshSessionHeaders(method, headers) {
1023
+ const cookie = this.composeCookieHeader();
1024
+ if (cookie)
1025
+ headers.Cookie = cookie;
1026
+ else
1027
+ delete headers.Cookie;
1028
+ if (isModifyingMethod(method))
1029
+ headers['X-CSRF-Token'] = this.csrfToken;
1030
+ }
1039
1031
  storeCookies(response) {
1040
- const setCookieHeaders = response.headers.getSetCookie();
1041
- if (!setCookieHeaders || setCookieHeaders.length === 0)
1042
- return;
1043
- for (const cookie of setCookieHeaders) {
1032
+ for (const cookie of response.headers.getSetCookie() ?? []) {
1044
1033
  // Set-Cookie: name=value; Path=/; HttpOnly; ...
1045
1034
  const nameValue = cookie.split(';')[0];
1046
1035
  if (!nameValue)
@@ -1053,18 +1042,18 @@ export class AdtHttpClient {
1053
1042
  this.cookieJar.set(name, value);
1054
1043
  }
1055
1044
  }
1056
- /** Build full URL with sap-client and sap-language query params */
1057
- buildUrl(path) {
1045
+ /** Add SAP context query params unless the caller sends that context in headers. */
1046
+ buildUrl(path, sapContextInHeaders = false) {
1058
1047
  const base = this.config.baseUrl.replace(/\/$/, '');
1059
1048
  const normalizedPath = path.startsWith('/') ? path : `/${path}`;
1060
1049
  const url = new URL(base + normalizedPath);
1061
- if (this.config.client) {
1050
+ if (this.config.client && !sapContextInHeaders) {
1062
1051
  url.searchParams.set('sap-client', this.config.client);
1063
1052
  }
1064
- if (this.config.language) {
1053
+ if (this.config.language && !sapContextInHeaders) {
1065
1054
  url.searchParams.set('sap-language', this.config.language);
1066
1055
  }
1067
- if (this.config.disableSaml) {
1056
+ if (this.config.disableSaml && !sapContextInHeaders) {
1068
1057
  url.searchParams.set('saml2', 'disabled');
1069
1058
  }
1070
1059
  return url.toString();
@@ -1101,7 +1090,37 @@ export class AdtHttpClient {
1101
1090
  * Node 22's built-in fetch embeds an older undici version whose dispatcher
1102
1091
  * interface is incompatible with npm undici@8 Agent/ProxyAgent instances.
1103
1092
  */
1104
- async doFetch(url, method, headers, body, options) {
1093
+ async doFetch(url, method, headers, body, options, resetOnUnauthorized = false) {
1094
+ const cookieNames = () => [...this.cookieJar.keys(), ...Object.keys(this.config.cookies ?? {})];
1095
+ const response = await this.securitySessionGate.run(() => hasSecuritySessionCookie(cookieNames()), async (waited) => {
1096
+ const generation = this.securitySessionGate.generation;
1097
+ if (waited) {
1098
+ // A preceding response may have replaced both fields while this send waited.
1099
+ // Keep the refreshed pair for this logical request's negotiation/retry paths too.
1100
+ this.refreshSessionHeaders(method, headers);
1101
+ }
1102
+ const response = await this.sendRequest(url, method, headers, body, options);
1103
+ const fetchingCsrf = headers['X-CSRF-Token']?.toLowerCase() === 'fetch';
1104
+ if (generation === this.securitySessionGate.generation) {
1105
+ // Store once at the headers boundary, before releasing the bootstrap owner.
1106
+ this.storeCookies(response);
1107
+ // Ordinary responses (including 404) can carry a token without proving a Fetch probe succeeded.
1108
+ const token = fetchingCsrf ? usableCsrfToken(response) : response.headers.get('x-csrf-token');
1109
+ if (token && token !== 'Required')
1110
+ this.csrfToken = token;
1111
+ // Reset before releasing waiters; a slow 401 body must not clear their new session.
1112
+ if (resetOnUnauthorized && response.status === 401)
1113
+ this.resetSession();
1114
+ }
1115
+ else if (fetchingCsrf) {
1116
+ await response.body?.cancel();
1117
+ throw new AdtNetworkError('SAP session changed during CSRF bootstrap. Retry the request.');
1118
+ }
1119
+ return response;
1120
+ }, options);
1121
+ return prepareBoundedResponse(response, url, options);
1122
+ }
1123
+ async sendRequest(url, method, headers, body, options) {
1105
1124
  throwIfRequestCancelled(options);
1106
1125
  // Forward the caller's W3C trace context to SAP so one trace spans agent → ARC-1 → SAP.
1107
1126
  // Empty unless the MCP client sent a valid `traceparent`; ARC-1 never originates a trace.
@@ -1128,7 +1147,7 @@ export class AdtHttpClient {
1128
1147
  ...(dispatcher ? { dispatcher } : {}),
1129
1148
  }, options?.attemptBudget));
1130
1149
  }
1131
- return prepareBoundedResponse(response, url, options);
1150
+ return response;
1132
1151
  }
1133
1152
  /**
1134
1153
  * Execute an HTTP request through the BTP connectivity proxy using standard
@@ -1212,52 +1231,10 @@ export class AdtHttpClient {
1212
1231
  function isModifyingMethod(method) {
1213
1232
  return ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method.toUpperCase());
1214
1233
  }
1215
- /**
1216
- * Parse RFC 7231 `Retry-After` header into a delay in milliseconds.
1217
- *
1218
- * Accepts both forms allowed by the spec:
1219
- * - delta-seconds (e.g. `"5"`)
1220
- * - HTTP-date (e.g. `"Wed, 12 May 2026 14:30:00 GMT"`)
1221
- *
1222
- * On missing, NaN, malformed, past-date, or negative input, falls back to `fallbackMs`.
1223
- * Always clamps to `[0, 60_000]` ms so a misbehaving gateway can't stall us indefinitely
1224
- * and a too-small/past value can't degenerate into a hot retry loop.
1225
- *
1226
- * Returns `{ delayMs, source }` — `source: 'header' | 'fallback'` lets audit events
1227
- * record whether the delay came from the server or from our jitter floor (useful for
1228
- * capacity tuning).
1229
- */
1230
- export function parseRetryAfter(header, fallbackMs) {
1231
- const clamp = (ms) => Math.max(0, Math.min(60_000, ms));
1232
- if (header == null || header === '') {
1233
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1234
- }
1235
- const trimmed = header.trim();
1236
- // delta-seconds form: integer (and only digits, optionally signed)
1237
- if (/^-?\d+$/.test(trimmed)) {
1238
- const seconds = Number.parseInt(trimmed, 10);
1239
- if (Number.isFinite(seconds)) {
1240
- return { delayMs: clamp(seconds * 1000), source: 'header' };
1241
- }
1242
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1243
- }
1244
- // HTTP-date form
1245
- const epochMs = Date.parse(trimmed);
1246
- if (Number.isFinite(epochMs)) {
1247
- return { delayMs: clamp(epochMs - Date.now()), source: 'header' };
1248
- }
1249
- return { delayMs: clamp(fallbackMs), source: 'fallback' };
1250
- }
1251
- /**
1252
- * Try to extract an accepted media type from a SAP 406 error response body.
1253
- *
1254
- * SAP sometimes includes the expected media type in error text, e.g.:
1255
- * "...expected application/vnd.sap.adt.transportorganizertree.v1+xml..."
1256
- * Returns the extracted media type or undefined if none found.
1257
- */
1258
- function inferAcceptFromError(body) {
1259
- const match = body.match(/application\/[\w.+-]+(?:\/[\w.+-]+)?/);
1260
- return match?.[0];
1234
+ /** A token on an unsuccessful response is not proof of authentication. */
1235
+ function usableCsrfToken(response) {
1236
+ const token = response.headers.get('x-csrf-token')?.trim();
1237
+ return response.ok && token && token.toLowerCase() !== 'required' ? token : undefined;
1261
1238
  }
1262
1239
  /**
1263
1240
  * Distinguish a real SAP logon page from a legitimate HTML response payload.