@mcp-abap-adt/connection 1.10.2 → 2.0.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 (44) hide show
  1. package/CHANGELOG.md +758 -0
  2. package/README.md +42 -11
  3. package/dist/__tests__/helpers/session.d.ts +15 -0
  4. package/dist/__tests__/helpers/session.d.ts.map +1 -0
  5. package/dist/__tests__/helpers/session.js +19 -0
  6. package/dist/auth/ntlm.d.ts +15 -0
  7. package/dist/auth/ntlm.d.ts.map +1 -1
  8. package/dist/auth/ntlm.js +38 -0
  9. package/dist/connection/AbstractAbapConnection.d.ts +163 -11
  10. package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
  11. package/dist/connection/AbstractAbapConnection.js +351 -14
  12. package/dist/connection/BaseAbapConnection.d.ts +5 -1
  13. package/dist/connection/BaseAbapConnection.d.ts.map +1 -1
  14. package/dist/connection/BaseAbapConnection.js +11 -1
  15. package/dist/connection/CertificateAbapConnection.d.ts +5 -1
  16. package/dist/connection/CertificateAbapConnection.d.ts.map +1 -1
  17. package/dist/connection/CertificateAbapConnection.js +11 -1
  18. package/dist/connection/JwtAbapConnection.d.ts +3 -2
  19. package/dist/connection/JwtAbapConnection.d.ts.map +1 -1
  20. package/dist/connection/JwtAbapConnection.js +19 -8
  21. package/dist/connection/KerberosAbapConnection.d.ts +5 -1
  22. package/dist/connection/KerberosAbapConnection.d.ts.map +1 -1
  23. package/dist/connection/KerberosAbapConnection.js +54 -3
  24. package/dist/connection/SamlAbapConnection.d.ts +5 -1
  25. package/dist/connection/SamlAbapConnection.d.ts.map +1 -1
  26. package/dist/connection/SamlAbapConnection.js +11 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/session/SessionLifecycle.d.ts +2 -9
  30. package/dist/session/SessionLifecycle.d.ts.map +1 -1
  31. package/dist/session/SessionLifecycle.js +8 -8
  32. package/docs/INDEX.md +106 -0
  33. package/docs/INSTALLATION.md +304 -0
  34. package/docs/JWT_AUTH_TOOLS.md +142 -0
  35. package/docs/MIGRATION-2.0.md +125 -0
  36. package/docs/SCOPE.md +44 -0
  37. package/docs/STATEFUL_SESSION_GUIDE.md +121 -0
  38. package/docs/USAGE.md +749 -0
  39. package/examples/README.md +112 -0
  40. package/examples/basic-connection.js +55 -0
  41. package/examples/jwt-with-token-refresh.js +87 -0
  42. package/examples/saml-connection.js +52 -0
  43. package/examples/websocket-transport.js +87 -0
  44. package/package.json +11 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,758 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `@mcp-abap-adt/connection` package will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.0.0] - 2026-07-29
11
+
12
+ The connection owns its session now, and says so. Before this release a stateful
13
+ ADT session could be replaced underneath a caller holding a lock — silently,
14
+ under an unchanged `sap-adt-connection-id`, with no way for either side to
15
+ notice. That is what orphans an edit lock and leaves an object inactive and
16
+ locked with nobody able to say whether the connector changed or the session
17
+ broke. Migration guide: [`docs/MIGRATION-2.0.md`](docs/MIGRATION-2.0.md).
18
+
19
+ ### Changed — BREAKING
20
+ - **`connect()` is mandatory, and it rejects when it fails.** `makeAdtRequest()` now refuses with `ADT_NOT_CONNECTED` unless the connection was explicitly connected, and `connect()` no longer swallows a failed establishment: it used to log a warning, resolve anyway and defer establishment to the first request, which was coherent only while that lazy path existed. Removing it means a swallowed failure would leave a connection reporting success while holding nothing. A caller that never checked `connect()` now fails at startup rather than at the first request — the better failure, but a new one.
21
+ - **Consumers must call `connect()` before the first request.** Requests are also refused after `disconnect()` and after `reset()`, until the next `connect()`. An in-flight request is not cut off: a teardown drains before it clears anything.
22
+
23
+ ### Added
24
+ - **`disconnect(): Promise<ITeardownReport>`.** Resolves rather than throws, and reports what the teardown could not finish: `abandonedWindows` names the lock windows still open when the bounded wait gave up, `releasePending` says a transport release is still outstanding. A caller learns which locks it must clean up by hand instead of discovering them on the next developer's screen.
25
+ - **`isConnected()` and `getSessionIdentity()`.** The session is observable now: whether a caller may work, and which ABAP session it would work over. The identity is derived from the `SAP_SESSIONID*` cookies and deliberately excludes `sap-XSRF_*`, which rotates on a token refresh *within* one session — folding it in would report an ordinary refresh as a new session.
26
+ - **`beginWindow(label)` / `endWindow(token)`.** Marks a span that must not lose its session, such as the interval between LOCK and UNLOCK. A teardown requested during an open window waits for it, bounded by an absolute ceiling measured from the request; on expiry the window is reported as abandoned rather than silently dropped.
27
+ - **The session lifecycle is on the shared contract, as capability atoms.** `AbstractAbapConnection` now declares `implements ISessionLifecycleAware, ILockWindowAware` from `@mcp-abap-adt/interfaces` 11.5.0, and `ITeardownReport`, `WindowToken`, `ADT_SESSION_ERROR` and `AdtSessionErrorCode` come from there. **Import them from `@mcp-abap-adt/interfaces`, not from this package** — it deliberately does not re-export them, because a contract type with two names is a contract type that can drift.
28
+
29
+ Atoms rather than five more methods on `IAbapConnection`: that interface is the minimum every transport can honour, and `RfcAbapConnection` owns no HTTP session and can open no lock window. Requiring these of every connection would force a transport with no session to implement a lie. Narrow to the atom you need — `IAbapConnection & ILockWindowAware` — and the compiler rejects an RFC connection at the call site instead of failing at runtime.
30
+
31
+ ### Fixed
32
+ - **A replaced session is now detected and raised instead of absorbed.** Responses are observed through one path that updates the cookies *and* applies the identity policy together; ten call sites used to update the cookies alone, which mutated the fingerprint and made a replacement indistinguishable from the session it replaced. A lost session raises `ADT_SESSION_REPLACED` and tears down, rather than letting the next request run against a session the caller never opened.
33
+ - **Session verdicts survive the retry layers.** Three nested catches — the CSRF retry, the 401-on-GET path and the endpoint fallback — used to swallow a session verdict and retry into a *new* session, where the replacement read as `unchanged` and the loss was gone for good.
34
+ - **A failed establishment leaves nothing behind.** A rejecting response could still carry a `Set-Cookie`, and every auth subclass treats a cookie as proof that auth is settled, so the *next* `connect()` went out with no credentials at all and failed for an unrelated reason. Transport state and the session identity are both dropped when `establishSession()` throws; `getSessionIdentity()` no longer names a session that was never established.
35
+ - **Kerberos: the first challenge is diagnosed, not the fourth.** The connect-time CSRF fetch inherited a 3-retry default while a GSS token is one-shot, so the diagnosis was drawn from a replayed — or credential-less — request. Multi-leg SPNEGO (RFC 4559) is still unsupported, but a landscape that needs it now fails at `connect()` saying so, instead of being misreported as rejected credentials.
36
+ - **The CSRF token fetch stays inside the ADT conversation** (also released in 1.10.1).
37
+ - **The test suite is green on a clean install.** `rfc-params.test.ts` called `jest.mock()` on `@mcp-abap-adt/sap-rfc-lite`, an **optional** dependency with a native build against the SAP NW RFC SDK. On any machine without that SDK npm skips it silently and `jest.mock()` cannot resolve it, so the suite failed — for everyone but whoever had a `node_modules` left over from an install that succeeded. Mocked `{ virtual: true }` now: the test replaces the module entirely and never wanted the real one.
38
+
39
+ ### Security
40
+ - Production audit is clean. `brace-expansion` remains reachable only through `jest` and is pinned by an override; it never ships.
41
+
42
+ ### Dependencies
43
+ - `@mcp-abap-adt/interfaces` 7.2.0 → **11.5.0**, now a real requirement rather than a version bump: this release imports the connection capability atoms from it. Crossing 8–11 was a no-op — those breaking changes are all in ADT object capability types, which the connector never imports — and it also closes the drift against `adt-clients` and `auth-providers`, both already on 11.x.
44
+
45
+ ## [1.10.2] - 2026-07-27
46
+
47
+ ### Added
48
+ - **`SessionLifecycle` — the session-lifecycle core, internal for now.** Owns what the connection cannot express today: session state and identity, a serializing tail for lifecycle transitions, admission accounting with a teardown epoch, lock windows counted per occurrence, and a drain bounded by an absolute ceiling. It knows nothing of SAP, HTTP, RFC or cookies — identities are opaque `name → value` maps, windows are opaque labels — which is why its 29 tests need no server. **Not exported from the package index and not yet used by any connection**, so this release changes no behaviour and no public API; it lands the piece that the rest of the session work (fr0ster/mcp-abap-connection#15) will be composed from. Design: `docs/superpowers/specs/2026-07-27-session-lifecycle-design.md` in `@mcp-abap-adt/adt-clients`.
49
+
50
+ ## [1.10.1] - 2026-07-27
51
+
52
+ ### Fixed
53
+ - **CSRF token fetch now stays inside the ADT conversation.** `makeAdtRequest` sends `sap-adt-connection-id` on every request, for all session types, but the token fetch assembled its own headers (auth + `x-csrf-token: fetch` + `Accept` + `Cookie`) and omitted it. A fetch triggered while a lock was held therefore reached the server as a caller that merely presented the same cookies, with no way for either side to relate it to the conversation that opened the session. The fetch now carries the connection id like every other request.
54
+
55
+ ## [1.10.0] - 2026-07-16
56
+
57
+ ### Added
58
+ - **Uninterruptible critical sections for lock → modify → unlock chains.** A short per-request timeout was aborting requests mid-flight during a stateful lock → PUT/activate → unlock chain; aborting the socket drops the stateful ADT session and orphans the lock handle, leaving the object **locked and inactive**. New connection methods `beginCriticalSection()` / `endCriticalSection()` (reference-counted) plus `isInCriticalSection()`: while in a critical section, `makeAdtRequest` raises the effective timeout to a large ceiling (`getCriticalSectionTimeout()`, env `SAP_TIMEOUT_CRITICAL`, default `600000` ms) instead of the short per-request timeout, so slow PUT/activate/unlock requests run to completion rather than being interrupted. Consumers wrap a mutating operation with `beginCriticalSection()` before locking and `endCriticalSection()` in a `finally` after unlocking. Additive and backward-compatible (no behavior change outside a critical section).
59
+
60
+ ## [1.9.1] - 2026-05-24
61
+
62
+ ### Added
63
+ - **NTLM hard-reject for Kerberos auth.** When `KerberosAbapConnection` receives a 401/403 whose `WWW-Authenticate` header indicates NTLM (direct `NTLM` scheme, or an NTLM token tunneled via `Negotiate` — base64 prefix `TlRMTVNTUAA` = `NTLMSSP\0`), it now throws a clear error instead of swallowing it. Prevents a silent downgrade to weaker NTLM; only Kerberos/SPNEGO is accepted. New `isNtlmChallenge()` helper (`src/auth/ntlm.ts`).
64
+
65
+ ## [1.9.0] - 2026-05-24
66
+
67
+ ### Added
68
+
69
+ - **Certificate (mTLS) authentication** — `CertificateAbapConnection` injects client-cert material into the axios `https.Agent` via a new protected `getHttpsAgentOptions()` hook on `AbstractAbapConnection`. Material loaded from PEM (`certPath`+`certKeyPath`) or PFX (`certPfxPath`+`certPassphrase`) by the injectable `FileCertificateMaterialLoader` (`ICertificateMaterialLoader`).
70
+ - **Kerberos / SPNEGO authentication** — `KerberosAbapConnection` generates a single-leg Negotiate token locally via `generateSpnegoToken()` (lazy wrapper over the optional `kerberos` native package, declared in `optionalDependencies`), sends `Authorization: Negotiate <token>` on the first request, then reuses the SAP session cookie.
71
+ - `createAbapConnection()` routes `authType: 'certificate'` and `'kerberos'`; both reject `connectionType: 'rfc'`. New optional `certLoader` factory option.
72
+ - `sapConfigSignature()` includes cert paths / SPN (secrets never embedded — passphrase recorded as `'set'`/null only).
73
+
74
+ ### Notes
75
+
76
+ - Certificate and Kerberos are connection-layer auth types (on-prem HTTP); they bypass the auth-broker and auth-providers. Requires `@mcp-abap-adt/interfaces@^7.2.0`.
77
+ - Both connections require `connect()` before the first request; calling a request first fails loudly (cert: throws on missing material; kerberos: throws on missing token).
78
+
79
+ ## [1.7.0] - 2026-04-14
80
+
81
+ ### Changed
82
+
83
+ - Update `@mcp-abap-adt/interfaces` to `^7.0.0` (adds `ServiceBindingVariant` type and `connect()` method in `IAbapConnection`)
84
+
85
+ ## 1.5.3 - 2026-03-12
86
+
87
+ ### Added
88
+ - **RFC stateful session support**: `setSessionType('stateful')` now injects `x-sap-adt-sessiontype: stateful` header and captures `set-cookie` from LOCK responses for cookie replay in subsequent requests (PUT, UNLOCK). This enables lock/update/unlock workflows for package objects over RFC, which require HTTP session ownership validation. `setSessionType('stateless')` clears the captured cookie.
89
+
90
+ ## 1.5.2 - 2026-03-12
91
+
92
+ ### Added
93
+ - **RFC debug logging**: `RfcAbapConnection` now logs full request headers, request body, response headers, and response body at `debug` level. Enable with `DEBUG_CONNECTORS=true` and `AUTH_LOG_LEVEL=debug`.
94
+
95
+ ## [1.5.1] - 2026-03-09
96
+
97
+ ### Fixed
98
+ - **RFC query params encoding**: `RfcAbapConnection.makeAdtRequest` now encodes `params` into the URI query string. Previously `params` were silently ignored, causing failures for package validation, transport checks, and any ADT operation using query parameters over RFC connections.
99
+
100
+ ## [1.4.2] - 2026-03-06
101
+
102
+ ### Added
103
+ - `reset()` method on `RfcAbapConnection` — delegates to `close()` for interface compatibility with HTTP connections.
104
+
105
+ ## [1.4.1] - 2026-03-06
106
+
107
+ ### Fixed
108
+ - Fix RFC STATUS_LINE parsing: use correct field names `STATUS_CODE`/`REASON_PHRASE` (not `CODE`/`REASON`). STATUS_CODE is returned as string — now parsed with `parseInt`.
109
+ - Remove `sap-client` URI parameter from RFC requests — the RFC session is already logged into the correct client via connection parameters. Adding `sap-client` caused "object not found" on some systems.
110
+ - Add fallback exception XML detection: when STATUS_LINE is empty (legacy systems), parse `<exc:exception>` body to derive HTTP status codes (404, 403, 409, 423, etc.).
111
+
112
+ ## [1.4.0] - 2026-03-06
113
+
114
+ ### Added
115
+ - `RfcAbapConnection` — RFC-based connection for legacy SAP systems (BASIS < 7.50) that don't support stateful HTTP sessions. Uses standard `SADT_REST_RFC_ENDPOINT` FM (the same FM that Eclipse ADT uses via JCo) to tunnel ADT REST requests over RFC. Solves HTTP 423 "invalid lock handle" on older systems.
116
+ - `authType: 'rfc'` support in `createAbapConnection()` factory.
117
+ - RFC connection parameters (ashost, sysnr) are derived from the existing `config.url` field — no config changes needed.
118
+
119
+ ### Changed
120
+ - Updated dependency `@mcp-abap-adt/interfaces` to `^2.7.0` (adds `'rfc'` to `SapAuthType` union).
121
+
122
+ ### Notes
123
+ - `node-rfc` is **not** a declared dependency. Users who need RFC connections must install it manually (`npm install node-rfc`) along with SAP NW RFC SDK.
124
+ - RFC connections are inherently stateful — `setSessionType()` is a no-op.
125
+
126
+ ## [1.1.0] - 2026-02-13
127
+
128
+ ### Added
129
+ - Added generic `GenericWebSocketTransport` implementation with injected WS factory and message envelope handling.
130
+ - Re-exported WebSocket transport interfaces from `@mcp-abap-adt/interfaces` and transport class from package root.
131
+
132
+ ### Changed
133
+ - Updated dependency `@mcp-abap-adt/interfaces` to `^2.4.0`.
134
+
135
+ ## [1.0.1] - 2026-02-10
136
+
137
+ ### Changed
138
+ - Dependency updates: `axios`, `commander`, `@biomejs/biome`, `@types/node`.
139
+
140
+ ## [1.0.0] - 2026-02-10
141
+
142
+ ### Added
143
+ - `SamlAbapConnection` for cookie-based SAML sessions and `createAbapConnection` support for `authType: 'saml'`.
144
+ - SAML session cookie support in `SapConfig` and `sapConfigSignature()`.
145
+ - Unit tests for SAML connection, connection factory routing, and config signature.
146
+
147
+ ### Changed
148
+ - **Conditional Logging Support**: Connection package now fully supports conditional logging via `undefined` logger
149
+ - When `undefined` is passed as logger parameter, connection operates silently (no logging output)
150
+ - This enables test environments to control logging verbosity via environment variables
151
+ - Tests can now pass `undefined` logger when `DEBUG_CONNECTION`, `DEBUG_CONN`, or `DEBUG_CONNECTORS` are not set
152
+ - Connection uses optional chaining (`logger?.info()`, `logger?.debug()`, etc.) for all logging calls
153
+ - No breaking changes - existing code with logger continues to work as before
154
+
155
+ ## [0.2.8] - 2025-12-24
156
+
157
+ ### Changed
158
+ - **Dependencies**: Updated `@mcp-abap-adt/interfaces` from `^0.2.5` to `^0.2.13`
159
+
160
+ ## [0.2.7] - 2025-12-23
161
+ ### Fixed
162
+ - Fixed LICENSE file - corrected copyright attribution (removed incorrect fork author)
163
+
164
+ ## [0.2.6] - 2025-12-22
165
+
166
+ ### Changed
167
+ - **Biome Migration**: Migrated from ESLint/Prettier to Biome for linting and formatting
168
+ - Added `@biomejs/biome` as dev dependency
169
+ - Added `lint`, `lint:check`, and `format` scripts to package.json
170
+ - Integrated Biome check into build process (`npx biome check src --diagnostic-level=error`)
171
+ - Updated Node.js imports to use `node:` protocol (`crypto`, `https`)
172
+ - **Type Safety**: Improved type safety by replacing `any` with `unknown`
173
+ - `AbstractAbapConnection.ts`: `updateCookiesFromResponse` method parameter changed from `Record<string, any>` to `Record<string, unknown>`
174
+ - `tokenRefresh.ts`: `error` parameter in catch block changed from `any` to `unknown` with added type guards
175
+
176
+ ### Fixed
177
+ - Fixed computed property access by using literal keys where possible (`Authorization`, `Accept`, `Cookie` headers)
178
+ - Fixed non-null assertions by adding proper null checks (`JwtAbapConnection.ts`)
179
+ - Fixed optional chaining usage in `tokenRefresh.ts`
180
+ - Removed unused imports (`AbapConnection.ts`)
181
+ - Improved error handling with proper type guards for `unknown` error types
182
+
183
+ ## [0.2.5] - 2025-12-21
184
+
185
+ ### Added
186
+ - **connectionFactory tokenRefresher**: `createAbapConnection()` now accepts optional 4th parameter `tokenRefresher`
187
+ - Passes through to `JwtAbapConnection` for automatic token refresh DI
188
+ - Enables external token management via `AuthBroker.createTokenRefresher()`
189
+
190
+ ## [0.2.4] - 2025-12-21
191
+
192
+ ### Added
193
+ - **ITokenRefresher Support**: `JwtAbapConnection` now supports automatic token refresh via dependency injection
194
+ - New optional `tokenRefresher` parameter in constructor
195
+ - If provided, 401/403 errors trigger automatic token refresh and request retry
196
+ - If not provided, legacy behavior (throw error on expired token)
197
+ - Works with `AuthBroker.createTokenRefresher(destination)` from `@mcp-abap-adt/auth-broker`
198
+
199
+ ### Changed
200
+ - **Dependencies**: Updated `@mcp-abap-adt/interfaces` to `^0.2.5`
201
+ - New `ITokenRefresher` interface for token management DI
202
+ - Simplified `IAbapConnection` interface
203
+
204
+ ### Usage Example
205
+ ```typescript
206
+ import { JwtAbapConnection } from '@mcp-abap-adt/connection';
207
+ import { AuthBroker } from '@mcp-abap-adt/auth-broker';
208
+
209
+ // Create token refresher from broker
210
+ const tokenRefresher = broker.createTokenRefresher('TRIAL');
211
+
212
+ // Inject into connection - 401/403 handled automatically
213
+ const connection = new JwtAbapConnection(config, logger, sessionId, tokenRefresher);
214
+ ```
215
+
216
+ ## [0.2.3] - 2025-12-19
217
+
218
+ ### Fixed
219
+ - **Network Error Detection**: Add proper detection and handling of network-level errors in `AbstractAbapConnection.makeAdtRequest()`
220
+ - Detect network errors: `ECONNREFUSED`, `ETIMEDOUT`, `ENOTFOUND`, `ECONNRESET`, `ENETUNREACH`, `EHOSTUNREACH`
221
+ - Skip retry logic for network errors (CSRF token retry, 401 cookie retry)
222
+ - Throw network errors immediately with clear error message
223
+ - Prevents confusing error messages when VPN is down or server is unreachable
224
+ - Network errors now clearly indicate infrastructure issues vs application errors
225
+
226
+ ### Changed
227
+ - **Error Handling**: Improved error handling logic to distinguish between network errors and HTTP errors
228
+ - Network errors (connection issues) are now handled separately from HTTP errors (401, 403, 404)
229
+ - No retry attempts for network errors (retries cannot fix infrastructure issues)
230
+ - Better error logging with network error context
231
+
232
+ ### Documentation
233
+ - Added "Network Error Detection" section to `docs/USAGE.md` with examples and best practices
234
+ - Documented all detected network error codes and their meanings
235
+ - Added error handling examples showing how to handle network vs HTTP errors
236
+
237
+ ## [0.2.2] - 2025-12-13
238
+
239
+ ### Fixed
240
+ - Add missing `ILogger` import from `@mcp-abap-adt/interfaces` to restore TypeScript build
241
+
242
+ ## [0.2.1] - 2025-12-13
243
+
244
+ ### Changed
245
+ - Dependency bump: `@mcp-abap-adt/interfaces` → `^0.1.16` to align with latest interfaces release
246
+ - Repository metadata: point package links to `fr0ster/mcp-abap-connection` (correct repo)
247
+
248
+ ## [0.2.0] - 2025-12-08
249
+
250
+ ### Breaking Changes
251
+
252
+ - **Token Refresh Removed**: Token refresh functionality has been completely removed from this package
253
+ - `refreshToken()` method removed from `JwtAbapConnection`
254
+ - `canRefreshToken()` method removed from `JwtAbapConnection`
255
+ - All automatic token refresh logic removed from connection classes
256
+ - Token refresh is now handled exclusively by `@mcp-abap-adt/auth-broker` package
257
+ - This is a breaking change - code that relied on connection-level token refresh will need to use auth-broker instead
258
+
259
+ - **Logger is Optional**: Logger parameter is now optional in all connection constructors
260
+ - `BaseAbapConnection`, `JwtAbapConnection`, and `createAbapConnection()` now accept `logger?: ILogger | null`
261
+ - All logger calls use optional chaining (`logger?.info()`, `logger?.debug()`, etc.)
262
+ - If no logger is provided, no logging output is produced (no-op behavior)
263
+ - This allows using connections without requiring a logger instance
264
+
265
+ - **Session Storage Removed**: Session storage functionality has been completely removed from this package
266
+ - `sessionStorage` parameter removed from all connection constructors (`BaseAbapConnection`, `JwtAbapConnection`, `createAbapConnection()`)
267
+ - All session storage methods removed: `setSessionStorage()`, `getSessionStorage()`, `loadSessionState()`, `saveSessionState()`, `clearSessionState()`, `getSessionState()`, `setSessionState()`
268
+ - `FileSessionStorage` utility class removed
269
+ - Session state persistence is now handled exclusively by `@mcp-abap-adt/auth-broker` package
270
+ - Connection package now handles only HTTP communication and session headers (cookies, CSRF tokens) without persistence
271
+ - This is a breaking change - code that relied on connection-level session storage will need to use auth-broker instead
272
+
273
+ ### Changed
274
+
275
+ - **Connection Package Scope**: Package now focuses solely on HTTP connection management
276
+ - Removed all token refresh logic from `JwtAbapConnection`
277
+ - Removed all token refresh logic from `connect()`, `makeAdtRequest()`, and `fetchCsrfToken()` methods
278
+ - Removed all session storage and state persistence logic
279
+ - Connection package now handles only HTTP communication and session headers (cookies, CSRF tokens)
280
+ - Token lifecycle management and session state persistence are delegated to auth-broker package
281
+
282
+ ### Removed
283
+
284
+ - **Token Refresh Methods**:
285
+ - `refreshToken()` method removed from `JwtAbapConnection`
286
+ - `canRefreshToken()` method removed from `JwtAbapConnection`
287
+ - `tokenRefreshInProgress` private field removed
288
+ - Import of `refreshJwtToken` utility removed
289
+
290
+ - **Token Refresh Tests**:
291
+ - `auto-refresh.test.ts` removed
292
+ - Replaced with simplified `jwt-connection.test.ts` that tests only configuration validation
293
+
294
+ - **Session Storage Components**:
295
+ - `FileSessionStorage` utility class removed
296
+ - `ISessionStorage` and `SessionState` type exports removed
297
+ - All session storage related imports and exports removed
298
+
299
+ ### Migration Guide
300
+
301
+ If you were using token refresh functionality:
302
+
303
+ **Before (0.1.x)**:
304
+ ```typescript
305
+ const connection = new JwtAbapConnection(config, logger);
306
+ if (connection.canRefreshToken()) {
307
+ await connection.refreshToken();
308
+ }
309
+ ```
310
+
311
+ **After (0.2.0)**:
312
+ ```typescript
313
+ // Token refresh is now handled by auth-broker
314
+ // Connection package only handles HTTP communication
315
+ const connection = new JwtAbapConnection(config, logger);
316
+ // No refreshToken() or canRefreshToken() methods available
317
+ ```
318
+
319
+ **Logger Usage**:
320
+ ```typescript
321
+ // Logger is now optional
322
+ const connection = new JwtAbapConnection(config); // No logger - no logging output
323
+ const connection = new JwtAbapConnection(config, logger); // With logger - logging enabled
324
+ const connection = new JwtAbapConnection(config, null); // Explicitly no logger
325
+ ```
326
+
327
+ If you were using session storage functionality:
328
+
329
+ **Before (0.1.x)**:
330
+ ```typescript
331
+ import { FileSessionStorage } from '@mcp-abap-adt/connection';
332
+
333
+ const sessionStorage = new FileSessionStorage();
334
+ const connection = new JwtAbapConnection(config, logger, sessionStorage);
335
+ await connection.saveSessionState();
336
+ const state = await connection.getSessionState();
337
+ ```
338
+
339
+ **After (0.2.0)**:
340
+ ```typescript
341
+ // Session storage is now handled by auth-broker
342
+ // Connection package only handles HTTP communication
343
+ const connection = new JwtAbapConnection(config, logger);
344
+ // No sessionStorage parameter, no saveSessionState() or getSessionState() methods
345
+ ```
346
+
347
+ ## [0.1.15] - 2025-12-05
348
+
349
+ ### Changed
350
+ - **Logger Interface Migration**: Migrated from specialized logger methods to standard `ILogger` interface
351
+ - Replaced `logger.csrfToken()` calls with standard `debug()` and `error()` methods
352
+ - Replaced `logger.tlsConfig()` calls with standard `debug()` method
353
+ - Now uses only `ILogger` interface from `@mcp-abap-adt/interfaces` without dependency on concrete logger implementation
354
+ - Follows Dependency Inversion Principle - depends on interface, not implementation
355
+
356
+ ### Added
357
+ - **npm Configuration**: Added `.npmrc` file with `prefer-online=true` to ensure packages are installed from npmjs.com registry instead of local file system dependencies
358
+
359
+ ## [0.1.14] - 2025-12-04
360
+
361
+ ### Added
362
+ - **Interfaces Package Integration**: Migrated to use `@mcp-abap-adt/interfaces` package for all interface definitions
363
+ - All interfaces now imported from shared package
364
+ - Backward compatibility maintained with type aliases
365
+ - Dependency on `@mcp-abap-adt/interfaces@^0.1.0` added
366
+
367
+ ### Changed
368
+ - **Interface Renaming**: Interfaces renamed to follow `I` prefix convention:
369
+ - `SapConfig` → `ISapConfig` (type alias for backward compatibility)
370
+ - `AbapConnection` → `IAbapConnection` (type alias for backward compatibility)
371
+ - `AbapRequestOptions` → `IAbapRequestOptions` (type alias for backward compatibility)
372
+ - `SessionState` → `ISessionState` (type alias for backward compatibility)
373
+ - `TokenRefreshResult` → `ITokenRefreshResult` (type alias for backward compatibility)
374
+ - `TimeoutConfig` → `ITimeoutConfig` (type alias for backward compatibility)
375
+ - Old names still work via type aliases for backward compatibility
376
+
377
+ ### Documentation
378
+ - **Responsibilities and Design Principles**: Added comprehensive documentation section explaining package responsibilities and design principles
379
+
380
+ ## [0.1.13] - 2025-12-01
381
+
382
+ ### Added
383
+ - **CSRF Configuration Export**: Exported `CSRF_CONFIG` and `CSRF_ERROR_MESSAGES` constants for consistent CSRF token handling across different connection implementations
384
+ - `CSRF_CONFIG`: Centralized constants for CSRF token fetching (retry count, delay, endpoint, headers)
385
+ - `CSRF_ERROR_MESSAGES`: Standardized error messages for CSRF token operations
386
+ - Enables other projects (e.g., Cloud SDK-based connections) to use the same CSRF configuration
387
+ - Rationale in commit `ba12a42`; the standalone proposal document it linked is no longer in the tree
388
+
389
+ ### Changed
390
+ - **CSRF Token Endpoint**: Updated CSRF token fetching to use `/sap/bc/adt/core/discovery` endpoint instead of `/sap/bc/adt/discovery`
391
+ - Lighter response payload
392
+ - Available on all SAP systems (on-premise and cloud)
393
+ - Standard ADT discovery endpoint
394
+
395
+ ## [0.1.12] - 2025-11-28
396
+
397
+ ### Changed
398
+ - **BREAKING**: Removed all file reading functionality from connection package:
399
+ - Connection package no longer reads `.env` files or any configuration files
400
+ - Connection package no longer depends on `dotenv` or file system operations for configuration
401
+ - Consumers must now pass `SapConfig` directly to connection constructors
402
+ - This change improves separation of concerns: connection layer is now purely about connection logic, not configuration management
403
+
404
+ ### Removed
405
+ - `loadEnvFile(envPath?: string): boolean` - Function that loaded `.env` files
406
+ - `loadConfigFromEnvFile(envPath?: string): SapConfig` - Convenience function that combined file loading and config reading
407
+ - `getConfigFromEnv(): SapConfig` - Function that read configuration from `process.env`
408
+ - All file system dependencies (`fs`, `path`) from `sapConfig.ts`
409
+ - All `dotenv` usage and dependencies from the package
410
+
411
+ ### Fixed
412
+ - Resolved `stdio` mode output corruption issues by removing `dotenv` dependency
413
+ - Connection package is now cleaner and more focused on connection logic only
414
+ - Configuration management is now the responsibility of consumers (e.g., `mcp-abap-adt`)
415
+
416
+ ### Migration Guide
417
+ If you were using `getConfigFromEnv()` or `loadConfigFromEnvFile()`:
418
+ 1. Read environment variables in your application code (using `dotenv` or manual parsing)
419
+ 2. Create `SapConfig` object from environment variables
420
+ 3. Pass `SapConfig` directly to `createAbapConnection()` or connection constructors
421
+
422
+ Example:
423
+ ```typescript
424
+ // Before (0.1.11 and earlier):
425
+ import { loadConfigFromEnvFile, createAbapConnection } from '@mcp-abap-adt/connection';
426
+ const config = loadConfigFromEnvFile();
427
+ const connection = createAbapConnection(config, logger);
428
+
429
+ // After (0.1.12+):
430
+ import { SapConfig, createAbapConnection } from '@mcp-abap-adt/connection';
431
+ // Load .env file in your application (using dotenv or manual parsing)
432
+ const config: SapConfig = {
433
+ url: process.env.SAP_URL!,
434
+ authType: 'jwt',
435
+ jwtToken: process.env.SAP_JWT_TOKEN!,
436
+ // ... other config
437
+ };
438
+ const connection = createAbapConnection(config, logger);
439
+ ```
440
+
441
+ ## [0.1.11] - 2025-11-25
442
+
443
+ ### Changed
444
+ - Updated documentation:
445
+ - `docs/JWT_AUTH_TOOLS.md`: Added examples showing token expiry information in generated `.env` files, explained automatic expiry detection feature
446
+ - `docs/INSTALLATION.md`: Updated JWT authentication section with token expiry examples, added manual setup option, updated version to 0.1.10
447
+ - Documentation now reflects the new token expiry feature introduced in 0.1.10 and provides clear guidance for users
448
+
449
+ ## [0.1.10] - 2025-11-25
450
+
451
+ ### Added
452
+ - Token expiry information in `.env` file generated by `sap-abap-auth` CLI:
453
+ - Automatic JWT token expiry date extraction and display
454
+ - Automatic refresh token expiry date extraction and display
455
+ - Human-readable expiry dates in UTC timezone
456
+ - ISO 8601 formatted expiry timestamps
457
+ - Comments added at the beginning of `.env` file for easy reference
458
+ - `getTokenExpiry()` utility function in `sap-abap-auth.js`:
459
+ - Decodes JWT tokens to extract expiration information
460
+ - Handles base64url encoding/decoding
461
+ - Returns structured expiry information (timestamp, date, readable format)
462
+ - Gracefully handles invalid or non-standard JWT tokens
463
+
464
+ ### Changed
465
+ - Enhanced `updateEnvFile()` function in `sap-abap-auth.js`:
466
+ - Now includes token expiry comments at the beginning of `.env` files
467
+ - Provides clear visibility into when tokens will expire
468
+ - Helps users proactively refresh tokens before expiration
469
+
470
+ ## [0.1.9] - 2025-11-23
471
+
472
+ ### Changed
473
+ - Updated documentation in README.md:
474
+ - Added information about new API methods (`getSessionId()`, `setSessionType()`)
475
+ - Enhanced `AbapConnection` interface documentation
476
+ - Added Changelog section with link to CHANGELOG.md
477
+ - Fixed documentation links to use `docs/` directory
478
+ - Specified current version (0.1.8) with key features
479
+ - Updated CHANGELOG.md:
480
+ - Added detailed descriptions for all versions (0.1.1-0.1.8)
481
+ - Fixed version ordering (newest to oldest)
482
+ - Added proper version links for all releases
483
+ - Documented all features, changes, and fixes for each version
484
+
485
+ ### Added
486
+ - Comprehensive version history documentation
487
+ - Version comparison links in CHANGELOG
488
+
489
+ ## [0.1.8] - 2025-11-22
490
+
491
+ ### Changed
492
+ - Refactored base URL handling in `AbstractAbapConnection`:
493
+ - Removed deprecated `setBaseUrl()` and `getBaseUrl()` methods
494
+ - Base URL now managed internally via constructor
495
+ - Improved URL construction consistency
496
+ - Enhanced session management:
497
+ - Added `getSessionId()` method to retrieve current session ID
498
+ - Added `setSessionType()` method to switch between stateful/stateless modes
499
+ - Session ID now auto-generated if not provided
500
+ - Improved session state management in `AbstractAbapConnection`
501
+
502
+ ### Added
503
+ - cSpell configuration for custom words in settings.json
504
+ - Automatic session ID generation when not explicitly provided
505
+ - GitHub Actions workflow for automated release process
506
+ - Environment file loading and configuration utilities
507
+ - `getSessionId()` and `setSessionType()` public methods for better session control
508
+
509
+ ### Removed
510
+ - Deprecated `setBaseUrl()` and `getBaseUrl()` methods from `AbstractAbapConnection`
511
+ - Use constructor parameter instead for setting base URL
512
+
513
+ ### Fixed
514
+ - Session ID generation now more robust
515
+ - Base URL handling more consistent across connection types
516
+
517
+ ## [0.1.7] - 2025-11-22
518
+
519
+ ### Changed
520
+ - Refactored base URL handling in `AbstractAbapConnection`:
521
+ - Base URL construction now centralized and consistent
522
+ - Improved URL parsing and validation
523
+ - Removed deprecated URL handling methods
524
+
525
+ ### Removed
526
+ - Deprecated methods for base URL manipulation
527
+ - Use constructor-based URL configuration instead
528
+
529
+ ## [0.1.6] - 2025-11-22
530
+
531
+ ### Added
532
+ - `getSessionId()` method to retrieve current session ID
533
+ - `setSessionType()` method to programmatically switch between stateful/stateless modes
534
+ - Better session management API for external control
535
+
536
+ ### Changed
537
+ - Enhanced session management with more granular control
538
+ - Session type can now be changed after connection creation
539
+
540
+ ## [0.1.5] - 2025-11-22
541
+
542
+ ### Changed
543
+ - Refactored session ID generation and state management in `AbstractAbapConnection`
544
+ - Improved session state persistence logic
545
+ - Better handling of session lifecycle
546
+
547
+ ### Fixed
548
+ - Session state management edge cases
549
+ - Session ID consistency across connection lifecycle
550
+
551
+ ## [0.1.4] - 2025-11-21
552
+
553
+ ### Added
554
+ - Automatic session ID generation when not explicitly provided
555
+ - Session ID now auto-generated using UUID if not specified
556
+ - Improved session management for stateful connections
557
+
558
+ ### Changed
559
+ - Session creation logic simplified - no manual ID required
560
+ - Default session behavior more intuitive
561
+
562
+ ## [0.1.3] - 2025-11-20
563
+
564
+ ### Added
565
+ - GitHub Actions workflow for automated release process
566
+ - Automated npm publishing on version tags
567
+ - CI/CD pipeline for package releases
568
+
569
+ ### Changed
570
+ - Release process now automated via GitHub Actions
571
+ - Version tagging triggers automatic npm publish
572
+
573
+ ## [0.1.2] - 2025-11-20
574
+
575
+ ### Changed
576
+ - Updated dependencies to latest versions
577
+ - Enhanced TypeScript configuration for better type safety
578
+ - Improved build output structure
579
+
580
+ ### Added
581
+ - Better TypeScript compiler options
582
+ - Stricter type checking enabled
583
+
584
+ ## 0.1.0 - 2024-11-14
585
+
586
+ ### Changed
587
+ - **BREAKING**: Architecture refactoring for proper separation of concerns:
588
+ - `connect()` method changed from concrete to **abstract** in `AbstractAbapConnection`
589
+ - Each authentication type now implements its own `connect()` logic:
590
+ - `BaseAbapConnection`: Basic auth with CSRF token fetch, logs warnings on errors
591
+ - `JwtAbapConnection`: JWT auth with automatic token refresh on 401/403 errors
592
+ - `fetchCsrfToken()` changed from `private` to `protected` for use by concrete implementations
593
+ - Added protected getters/setters: `getCsrfToken()`, `setCsrfToken()`, `getCookies()`
594
+ - Removed ALL JWT-specific logic from `AbstractAbapConnection`:
595
+ - Removed JWT expiration checks from `connect()`
596
+ - Removed JWT error handling from base class
597
+ - Base class is now completely auth-agnostic
598
+ - `JwtAbapConnection.connect()` now handles:
599
+ - Token expiration detection (401/403 errors)
600
+ - Permission vs auth error distinction (`ExceptionResourceNoAccess` check)
601
+ - Automatic token refresh and retry
602
+ - `JwtAbapConnection.makeAdtRequest()` override handles JWT refresh for regular requests
603
+ - Previous architecture cleanup (from earlier versions):
604
+ - `BaseAbapConnection` (abstract) → `AbstractAbapConnection`
605
+ - `OnPremAbapConnection` → `BaseAbapConnection`
606
+ - `CloudAbapConnection` → `JwtAbapConnection`
607
+
608
+ ### Added
609
+ - Automatic JWT token refresh functionality for cloud connections
610
+ - Auto-refresh on 401/403 errors in both `connect()` and `makeAdtRequest()`
611
+ - Permission error detection: skips refresh for "ExceptionResourceNoAccess", "No authorization", "Missing authorization"
612
+ - `canRefreshToken()` method to check if refresh credentials available
613
+ - `refreshToken()` method to refresh JWT using UAA OAuth2 endpoint
614
+ - Concurrent refresh protection (prevents multiple simultaneous refresh attempts)
615
+ - Protected helper methods in `AbstractAbapConnection` for subclass use:
616
+ - `fetchCsrfToken()` - CSRF token fetching with retry logic
617
+ - `getCsrfToken()`, `setCsrfToken()` - CSRF token management
618
+ - `getCookies()` - Cookie access for concrete implementations
619
+ - Unit tests for auto-refresh logic (`src/__tests__/auto-refresh.test.ts`)
620
+ - Documentation structure:
621
+ - `docs/INSTALLATION.md` - Installation guide
622
+ - `docs/USAGE.md` - Usage examples and API documentation
623
+ - `docs/CUSTOM_SESSION_STORAGE.md` - Custom session storage implementation
624
+ - Example files:
625
+ - `examples/basic-connection.js` - Simple connection example
626
+ - `examples/session-persistence.js` - FileSessionStorage usage
627
+ - Updated `examples/README.md` with all examples
628
+
629
+ ### Removed
630
+ - JWT-specific logic from `AbstractAbapConnection`:
631
+ - Removed `isJwtExpiredError()` helper method
632
+ - Removed JWT refresh logic from base `connect()` method
633
+ - Removed JWT error messages from abstract class
634
+ - `AbstractAbapConnection` from public exports (internal use only)
635
+ - Only `BaseAbapConnection` and `JwtAbapConnection` are exported publicly
636
+ - `AUTO_REFRESH_IMPROVEMENTS.md` (temporary document, content moved to CHANGELOG)
637
+ - `CONNECTION_LAYER_ROADMAP.md` (roadmap belongs in root project)
638
+ - `PUBLICATION_ROADMAP.md` (roadmap belongs in root project)
639
+
640
+ ### Fixed
641
+ - JWT token refresh now properly handles connection errors (401/403 during initial connect)
642
+ - Permission errors (403 with "ExceptionResourceNoAccess") no longer trigger JWT refresh loops
643
+ - Proper separation: base class handles HTTP/session, concrete classes handle auth-specific errors
644
+ - Auto-refresh not triggering due to `canRefreshToken()` returning false
645
+ - Root cause: Test configuration not reading UAA credentials from environment
646
+ - Fixed in `packages/adt-clients` by updating `getConfig()` to read UAA variables
647
+
648
+ ## 0.1.0 - 2024-11-14
649
+
650
+ ### Changed
651
+ - **BREAKING**: Architecture refactoring for proper separation of concerns:
652
+ - `connect()` method changed from concrete to **abstract** in `AbstractAbapConnection`
653
+ - Each authentication type now implements its own `connect()` logic:
654
+ - `BaseAbapConnection`: Basic auth with CSRF token fetch, logs warnings on errors
655
+ - `JwtAbapConnection`: JWT auth with automatic token refresh on 401/403 errors
656
+ - `fetchCsrfToken()` changed from `private` to `protected` for use by concrete implementations
657
+ - Added protected getters/setters: `getCsrfToken()`, `setCsrfToken()`, `getCookies()`
658
+ - Removed ALL JWT-specific logic from `AbstractAbapConnection`:
659
+ - Removed JWT expiration checks from `connect()`
660
+ - Removed JWT error handling from base class
661
+ - Base class is now completely auth-agnostic
662
+ - `JwtAbapConnection.connect()` now handles:
663
+ - Token expiration detection (401/403 errors)
664
+ - Permission vs auth error distinction (`ExceptionResourceNoAccess` check)
665
+ - Automatic token refresh and retry
666
+ - `JwtAbapConnection.makeAdtRequest()` override handles JWT refresh for regular requests
667
+ - Previous architecture cleanup (from earlier versions):
668
+ - `BaseAbapConnection` (abstract) → `AbstractAbapConnection`
669
+ - `OnPremAbapConnection` → `BaseAbapConnection`
670
+ - `CloudAbapConnection` → `JwtAbapConnection`
671
+
672
+ ### Added
673
+ - Initial release of `@mcp-abap-adt/connection` package
674
+ - Support for Basic Auth (on-premise systems)
675
+ - Support for JWT/OAuth2 (SAP BTP cloud systems)
676
+ - CSRF token management
677
+ - Cookie-based session management
678
+ - `FileSessionStorage` for session persistence
679
+ - `ISessionStorage` interface for custom session storage
680
+ - CLI tool (`sap-abap-auth`) for browser-based authentication
681
+ - TypeScript type definitions
682
+ - Configurable timeouts for different operation types
683
+ - Custom logger interface (`ILogger`)
684
+ - Connection factory (`createAbapConnection()`)
685
+ - `BaseAbapConnection` for basic auth (formerly `OnPremAbapConnection`)
686
+ - `JwtAbapConnection` for JWT auth (formerly `CloudAbapConnection`)
687
+ - Session state management (`getSessionState()`, `setSessionState()`)
688
+ - Automatic JWT token refresh functionality for cloud connections
689
+ - Auto-refresh on 401/403 errors in both `connect()` and `makeAdtRequest()`
690
+ - Permission error detection: skips refresh for "ExceptionResourceNoAccess", "No authorization", "Missing authorization"
691
+ - `canRefreshToken()` method to check if refresh credentials available
692
+ - `refreshToken()` method to refresh JWT using UAA OAuth2 endpoint
693
+ - Concurrent refresh protection (prevents multiple simultaneous refresh attempts)
694
+ - Protected helper methods in `AbstractAbapConnection` for subclass use:
695
+ - `fetchCsrfToken()` - CSRF token fetching with retry logic
696
+ - `getCsrfToken()`, `setCsrfToken()` - CSRF token management
697
+ - `getCookies()` - Cookie access for concrete implementations
698
+ - Unit tests for auto-refresh logic (`src/__tests__/auto-refresh.test.ts`)
699
+ - Documentation structure:
700
+ - `docs/INSTALLATION.md` - Installation guide
701
+ - `docs/USAGE.md` - Usage examples and API documentation
702
+ - `docs/CUSTOM_SESSION_STORAGE.md` - Custom session storage implementation
703
+ - `docs/STATEFUL_SESSION_GUIDE.md` - Session state management guide
704
+ - Example files:
705
+ - `examples/basic-connection.js` - Simple connection example
706
+ - `examples/session-persistence.js` - FileSessionStorage usage
707
+ - `examples/README.md` with all examples
708
+
709
+ ### Removed
710
+ - JWT-specific logic from `AbstractAbapConnection`:
711
+ - Removed `isJwtExpiredError()` helper method
712
+ - Removed JWT refresh logic from base `connect()` method
713
+ - Removed JWT error messages from abstract class
714
+ - `AbstractAbapConnection` from public exports (internal use only)
715
+ - Only `BaseAbapConnection` and `JwtAbapConnection` are exported publicly
716
+
717
+ ### Fixed
718
+ - JWT token refresh now properly handles connection errors (401/403 during initial connect)
719
+ - Permission errors (403 with "ExceptionResourceNoAccess") no longer trigger JWT refresh loops
720
+ - Proper separation: base class handles HTTP/session, concrete classes handle auth-specific errors
721
+ [Unreleased]: https://github.com/fr0ster/mcp-abap-connection/compare/v2.0.0...HEAD
722
+ [2.0.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.10.2...v2.0.0
723
+ [1.10.2]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.10.1...v1.10.2
724
+ [1.10.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.10.0...v1.10.1
725
+ [1.10.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.9.1...v1.10.0
726
+ [1.9.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.9.0...v1.9.1
727
+ [1.9.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.7.0...v1.9.0
728
+ [1.7.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.5.1...v1.7.0
729
+ [1.5.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.4.2...v1.5.1
730
+ [1.4.2]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.4.1...v1.4.2
731
+ [1.4.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.4.0...v1.4.1
732
+ [1.4.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.1.0...v1.4.0
733
+ [1.1.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.0.1...v1.1.0
734
+ [1.0.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v1.0.0...v1.0.1
735
+ [1.0.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.8...v1.0.0
736
+ [0.2.8]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.7...v0.2.8
737
+ [0.2.7]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.6...v0.2.7
738
+ [0.2.6]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.5...v0.2.6
739
+ [0.2.5]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.4...v0.2.5
740
+ [0.2.4]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.3...v0.2.4
741
+ [0.2.3]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.2...v0.2.3
742
+ [0.2.2]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.1...v0.2.2
743
+ [0.2.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.2.0...v0.2.1
744
+ [0.2.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.15...v0.2.0
745
+ [0.1.15]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.14...v0.1.15
746
+ [0.1.14]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.13...v0.1.14
747
+ [0.1.13]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.12...v0.1.13
748
+ [0.1.12]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.11...v0.1.12
749
+ [0.1.11]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.10...v0.1.11
750
+ [0.1.10]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.9...v0.1.10
751
+ [0.1.9]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.8...v0.1.9
752
+ [0.1.8]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.7...v0.1.8
753
+ [0.1.7]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.6...v0.1.7
754
+ [0.1.6]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.5...v0.1.6
755
+ [0.1.5]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.4...v0.1.5
756
+ [0.1.4]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.3...v0.1.4
757
+ [0.1.3]: https://github.com/fr0ster/mcp-abap-connection/compare/v0.1.2...v0.1.3
758
+ [0.1.2]: https://github.com/fr0ster/mcp-abap-connection/releases/tag/v0.1.2