@mcp-abap-adt/auth-broker 5.0.1 → 5.0.4

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 (3) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +36 -10
  3. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -9,6 +9,63 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  Thank you to all contributors! See [CONTRIBUTORS.md](../../CONTRIBUTORS.md) for the complete list.
11
11
 
12
+ ## [5.0.4] - 2026-10-12
13
+
14
+ The first published release after 5.0.1. The code is the same as 5.0.2 and 5.0.3, which were
15
+ tagged but not published. It is released together with auth-broker-cli 3.1.1, so that one
16
+ publish from the main checkout carries both. 5.0.2 (built and tested on auth-stores 5) and
17
+ 5.0.3 (tests on connection 14.1.0, the README's connection note) arrive with 5.0.4.
18
+
19
+ ## [5.0.3] - 2026-10-12
20
+
21
+ Development only; the published library is unchanged.
22
+
23
+ ### Changed
24
+ - The tests run on `@mcp-abap-adt/connection` 14.1.0 (a dev dependency, `^14.1.0`):
25
+ its `disconnect()` sends the session's logoff, so a connection the broker's
26
+ tests and live checks close no longer leaves its SAP session open until the
27
+ server's timeout. The connection is the consumer's; the broker does not
28
+ depend on it.
29
+ - README: a consumer should use `@mcp-abap-adt/connection` 14.1.0 or later. From
30
+ 14.1.0, `disconnect()` ends the SAP session.
31
+
32
+ ## [5.0.2] - 2026-10-11
33
+
34
+ Built and tested on `@mcp-abap-adt/auth-stores` 5.0.0; the code is the same as
35
+ 5.0.1. auth-stores is not a dependency of the library: the consumer composes
36
+ the stores, and 5.0.2 works with auth-stores 4 or 5 alike.
37
+
38
+ ### Migration (for a consumer moving to auth-stores 5)
39
+
40
+ - **A session file with no binding keys beside its credential** — written by
41
+ auth-stores 2.x/3.0.0, auth-broker 3.x, or by hand — is no longer composed a
42
+ binding by the store and read as unbound (one login). auth-stores 5 refuses
43
+ the record whole with a `StorageError` (`code: 'STORAGE_ERROR'`,
44
+ `reason: 'record-format'`, fixed words, no value of the record), and the
45
+ broker passes it unchanged to the caller of `getProvider` and the token API
46
+ (every row that reads the session; the broker's own `client_credentials`
47
+ reads none, and its new credential replaces the record). This is 5.0.0's
48
+ rule that a store's read failure other than `FILE_NOT_FOUND` reaches the
49
+ caller, not a change of the broker.
50
+ - **What to do:** regenerate the session with
51
+ `mcp-auth --service-key <key.json> --output <file> --type abap|xsuaa`, or
52
+ remove its session lines; a file holding only the means is no session.
53
+ `@mcp-abap-adt/auth-broker-cli` 3.1.0 (released together) does it for you:
54
+ `mcp-auth --env <file>` or `--destination <name>` over such a file discards
55
+ its session and logs in anew, the means kept byte for byte.
56
+
57
+ ### Changed
58
+ - Dev dependency `@mcp-abap-adt/auth-stores` ^5.0.0.
59
+ - Tests: a pre-3.1.0 session file, and a 4.x token beside `issuedFor` alone,
60
+ now assert the store's `record-format` error reaching the caller — no
61
+ request, no login, no write, the file byte for byte, no record value in the
62
+ error or the log — where they asserted a login over a composed binding.
63
+
64
+ ### Documentation
65
+ - README (*Errors*, *A Credential Stays Bound to Its Identity*, the upgrade
66
+ note), `docs/` and `CLAUDE.md` describe the record-format refusal and name
67
+ auth-stores 5.
68
+
12
69
  ## [5.0.1] - 2026-10-09
13
70
 
14
71
  Development only; the code is the same as 5.0.0.
package/README.md CHANGED
@@ -16,10 +16,14 @@ the renewal strategy's you give it; where means and secrets live is the stores'
16
16
  short — a token destination needs two options the broker has no default for (`renewal`,
17
17
  `onWriteFailure`); every failure is an `AuthProviderFailure` read through
18
18
  `@mcp-abap-adt/auth-errors`; every session written before 5.0.0 reads as unbound once, so each
19
- token destination logs in once after the upgrade.
19
+ token destination logs in once after the upgrade. A session file with no binding keys at all
20
+ (written before auth-stores 3.1.0, or by hand) is refused by auth-stores 5 as a whole, and that
21
+ error reaches you: regenerate it with `mcp-auth` (see [*Errors*](#errors)) — from
22
+ auth-broker-cli 3.1.1, `mcp-auth --env <file>` (or `--destination <name>`) over such a file
23
+ discards its session and logs in anew.
20
24
 
21
25
  The `mcp-auth` command that writes destination files is
22
- [`@mcp-abap-adt/auth-broker-cli`](../auth-broker-cli/README.md) (3.0.0, on this version), in the
26
+ [`@mcp-abap-adt/auth-broker-cli`](../auth-broker-cli/README.md) (3.1.1, on this version), in the
23
27
  same repository. This package has no `bin`.
24
28
 
25
29
  ## Features
@@ -39,8 +43,8 @@ same repository. This package has no `bin`.
39
43
  npm install @mcp-abap-adt/auth-broker @mcp-abap-adt/auth-providers @mcp-abap-adt/auth-errors @mcp-abap-adt/auth-stores
40
44
  ```
41
45
 
42
- 5.0.0 depends on `@mcp-abap-adt/auth-providers` `^6.0.0`, `@mcp-abap-adt/auth-errors`
43
- `^2.1.1`, `@mcp-abap-adt/interfaces-auth` `^7.5.0`, `@mcp-abap-adt/interfaces-auth-sap`
46
+ 5.0.4 depends on `@mcp-abap-adt/auth-providers` `^6.0.0`, `@mcp-abap-adt/auth-errors`
47
+ `^2.2.0`, `@mcp-abap-adt/interfaces-auth` `^7.5.0`, `@mcp-abap-adt/interfaces-auth-sap`
44
48
  `^3.3.0`, `@mcp-abap-adt/interfaces-auth-broker` `^1.3.0` and
45
49
  `@mcp-abap-adt/interfaces-utils` `^1.1.0`. Declare `auth-providers` yourself — the renewal
46
50
  strategies (`refreshThenLogin`, `refreshOnly`) and the interactive strategies come from it —
@@ -312,7 +316,7 @@ success — and the write runs on, landing or failing on its own.
312
316
 
313
317
  **The store's contract.** `saveSession` settles: it resolves or rejects. A store whose
314
318
  `saveSession` never settles holds its destination's queue; avoiding that is yours (each waiting
315
- caller is still released by its own signal). auth-stores 4's `saveSession` **merges** — a field
319
+ caller is still released by its own signal). auth-stores 5's `saveSession` **merges** — a field
316
320
  left out keeps what is stored — so the broker states every field that must not survive:
317
321
 
318
322
  | What the provider reported | What one `saveSession` writes |
@@ -439,6 +443,18 @@ means lacking what the record needs, or no `serviceUrl`) gets a `debug` line ins
439
443
  start. An OIDC destination with explicit endpoints and a client but no issuer is fully stated,
440
444
  and is reused after a restart when its means are unchanged.
441
445
 
446
+ **A record the store refuses is not "no session".** auth-stores 5 reads a session only in its
447
+ own format — beside a token or cookies, both binding keys (`SAP_ISSUED_FOR` / `SAP_ISSUED_BY`,
448
+ or the `XSUAA_*` pair), present even when empty — and refuses any other record as a whole with
449
+ a `StorageError` (`reason: 'record-format'`): a file written by auth-stores 2.x/3.0.0 or
450
+ auth-broker 3.x, or by hand. The broker does not read that as an absent session and log in over
451
+ it; `getProvider` and the token API reject with the store's error, unchanged, before any
452
+ request (every row that reads the session; the broker's own `client_credentials` reads none,
453
+ and its new credential replaces the record). Regenerate the session with `mcp-auth`: from
454
+ auth-broker-cli 3.1.1, a run over the file (`--env`, `--destination`) discards its session — the
455
+ session keys alone, in a private copy, the original written only after the new login is stored —
456
+ and logs in anew.
457
+
442
458
  **The `none` rows** present a credential the broker cannot obtain again, so a mismatch is
443
459
  refused, not discarded: a `DestinationConfigError` naming `issuedFor` when the stored resource
444
460
  differs or is absent (or the means state no `serviceUrl`), and `issuedBy` when the stored record
@@ -468,7 +484,7 @@ import { bindingOf } from '@mcp-abap-adt/auth-broker';
468
484
  const means = await keyStore.getConnectionConfig('DEV'); // saml / none
469
485
  await sessionStore.saveSession('DEV', {
470
486
  sessionCookies: cookies,
471
- refreshToken: '', // auth-stores 4 merges: clear what an earlier session left
487
+ refreshToken: '', // auth-stores 5 merges: clear what an earlier session left
472
488
  ...bindingOf(means ?? {}),
473
489
  // { issuedFor: 'https://dev.example.com:443?sap-client=100',
474
490
  // issuedBy: 'mcp-abap-adt-binding/2;saml/none;;;;;;;;;;;;' }
@@ -829,6 +845,10 @@ const renewed = await tokenRefresher.refreshToken();
829
845
  A `@mcp-abap-adt/connection` 14 connector takes an `IAuthProvider` instead: give it `await
830
846
  broker.getProvider('TRIAL', { signal })`.
831
847
 
848
+ Use `@mcp-abap-adt/connection` 14.1.0 or later. From 14.1.0 its `disconnect()` sends the
849
+ session's logoff. An earlier 14.x left each closed connection's SAP session open until the
850
+ server's own timeout, so a process that connects again and again collects sessions.
851
+
832
852
  ## Errors
833
853
 
834
854
  **A provider's failure passes as the same object.** Whatever a provider throws from
@@ -930,7 +950,13 @@ needs a clientAuthentication strategy`.
930
950
 
931
951
  - **A store's read failure** (anything but `FILE_NOT_FOUND`, which is absence) reaches the
932
952
  caller as the store raised it — your collaborator's error, returned to you, also through the
933
- shared resolution. A store that answers `null`, or fails with `FILE_NOT_FOUND` (logged at
953
+ shared resolution. With auth-stores 5 that includes a session record not of the store's
954
+ format: a `StorageError` with `code: 'STORAGE_ERROR'` and `reason: 'record-format'`, in the
955
+ store's fixed words (`AbapSessionStore: the stored session for "<destination>" is not in this
956
+ store's format; regenerate it with mcp-auth`) — no value of the record. Regenerate the session
957
+ (`mcp-auth --service-key <key.json> --output <file>`, or from auth-broker-cli 3.1.1
958
+ `mcp-auth --env <file>`, which discards the refused session and logs in anew), or remove its
959
+ session lines. A store that answers `null`, or fails with `FILE_NOT_FOUND` (logged at
934
960
  debug), means "nothing here".
935
961
  - **The constructor's argument checks** (`AuthBroker: sessionStore is required`, …) are plain
936
962
  `Error`s naming option names: a programming error.
@@ -983,7 +1009,7 @@ its level from `AUTH_LOG_LEVEL`.)
983
1009
 
984
1010
  ### File Structure
985
1011
 
986
- With `@mcp-abap-adt/auth-stores` 4 one `<destination>.env` file can hold a destination whole,
1012
+ With `@mcp-abap-adt/auth-stores` 5 one `<destination>.env` file can hold a destination whole,
987
1013
  each store reading and writing only its own keys — the means through `EnvDestinationStore`, the
988
1014
  secret through `AbapSessionStore` (or both in separate directories, as you compose them):
989
1015
 
@@ -1171,7 +1197,7 @@ What a 4.x consumer must now do, row by row. The full list of changes is the
1171
1197
 
1172
1198
  | 4.x | 5.0.0 — what to do |
1173
1199
  |---|---|
1174
- | `@mcp-abap-adt/auth-providers` 5, `interfaces-auth` 3, `auth-stores` 3 | auth-providers `^6.0.0`, interfaces-auth `^7.5.0`, auth-errors `^2.1.1`, auth-stores `^4.0.0`; one installed copy of each contract (`npm ls`) |
1200
+ | `@mcp-abap-adt/auth-providers` 5, `interfaces-auth` 3, `auth-stores` 3 | auth-providers `^6.0.0`, interfaces-auth `^7.5.0`, auth-errors `^2.1.1`, auth-stores `^4.0.0` (`^5.0.0` from 5.0.4, the first published since 5.0.1: a session record without binding keys is refused, see *Errors*); one installed copy of each contract (`npm ls`) |
1175
1201
  | token rows renewed by the provider's built-in rule | pass `renewal: () => refreshThenLogin()` — 4.x's steps; without `renewal` a token row is refused (`missingFields: ['renewal']`) |
1176
1202
  | a `getProvider` provider's failed write never failed the authentication; the token API threw the store's error | pass `onWriteFailure`: `'continue'` keeps 4.x's connector behaviour (best effort); `'fail'` keeps 4.x's token-API behaviour and extends it to the connector and to every later call of the destination while the write is pending. Without it a destination that writes a secret is refused |
1177
1203
  | errors of the token API: auth-providers 5.x classes (`ValidationError`, `BrowserAuthError`, `RefreshError`, …) | `AuthProviderFailure`: read it with `readFailure(error, operation)` and `matchKind` (auth-errors); auth-providers' *Migrating to 6.0.0* maps each class to its kind |
@@ -1215,7 +1241,7 @@ npm test -w @mcp-abap-adt/auth-broker -- AuthBroker.test.ts -t "name of the case
1215
1241
  ```
1216
1242
 
1217
1243
  Tests run sequentially (`maxWorkers: 1`, `maxConcurrency: 1`). The broker suites need nothing:
1218
- fake stores of the contract or auth-stores 4 in temporary directories, real providers, a token
1244
+ fake stores of the contract or auth-stores 5 in temporary directories, real providers, a token
1219
1245
  endpoint the test starts on `127.0.0.1`. `AuthBroker.integration.test.ts` reads real service
1220
1246
  keys and sessions only when `packages/auth-broker/tests/test-config.yaml` exists (from the
1221
1247
  template beside it); without it every case returns at once. The stand (`npm run test:stand`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/auth-broker",
3
- "version": "5.0.1",
3
+ "version": "5.0.4",
4
4
  "description": "Per-destination credential broker for SAP BTP and ABAP: the IAuthProvider a destination states, built from its key store and session store, with every secret it obtains stored back; and a token API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -65,8 +65,8 @@
65
65
  },
66
66
  "devDependencies": {
67
67
  "@mcp-abap-adt/auth-mocks": "^0.4.0",
68
- "@mcp-abap-adt/auth-stores": "^4.0.0",
69
- "@mcp-abap-adt/connection": "^14.0.0",
68
+ "@mcp-abap-adt/auth-stores": "^5.0.0",
69
+ "@mcp-abap-adt/connection": "^14.1.0",
70
70
  "@mcp-abap-adt/logger": "^0.4.0",
71
71
  "@types/js-yaml": "^4.0.9",
72
72
  "js-yaml": "^4.1.1",