@mcp-abap-adt/interfaces-adt 20.2.0 → 21.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,132 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [21.0.0] - 2026-10-27
11
+
12
+ ### Added
13
+
14
+ - **The ADT type tables**, one per release variant: `ADT_TYPES_ONPREM`
15
+ (S/4HANA 2025 on-premise), `ADT_TYPES_CLOUD` (ABAP cloud) and
16
+ `ADT_TYPES_BASIS_740` (SAP_BASIS 7.40 SP04), `as const`, keyed by API — the
17
+ client's factory name. Each entry holds its `kind`, its `collection` and its
18
+ `codes`; each code its `parent` API, `nameMaxLength`, `operations` and
19
+ `evidence`, the corpus case of the release's `typestructure` answer, and,
20
+ where it lives elsewhere than its API, its own `collection` (the enhancement
21
+ codes: `/sap/bc/adt/enhancements/enhoxhh`, `/enhoxhb`, `/enhsxsb`). The
22
+ local class includes and the transport request are entries with
23
+ `codes: {}`, their `parent`, `operations` and `evidence` on the entry. An
24
+ API the 7.40 client refuses whole is absent from its table, and an operation
25
+ it refuses is absent from its code.
26
+ - The operations' closed vocabulary, `AdtOperation`. The ABAP Unit runners'
27
+ four members are four operations, `unitTestRun`, `unitTestRunSync`,
28
+ `unitTestStatus` and `unitTestResult`, because 7.40 serves them apart: there
29
+ `run` and `runSync` are served for a class, a program and a function group,
30
+ only `runSync` for a function module, and `getStatus` and `getResult` for
31
+ none (no run id to poll or fetch).
32
+ - The entry shape every table `satisfies` (`AdtApiTable<R>`, `AdtApiEntry<R>`,
33
+ `IAdtCodedApiEntry<R>`, `IAdtCodelessApiEntry<R>`, `IAdtCodeFacts<R>`,
34
+ `AdtApiName`, `AdtOperations`, `AdtCollection`, `AdtTypeEvidence<R>`,
35
+ `AdtCheckedTable<T>`): a misspelt field, an operation outside the
36
+ vocabulary, an API with no factory, another release's evidence, a codeless
37
+ entry without evidence or a coded entry without a code does not compile.
38
+ - The variants and the types derived from the tables: `AdtVariant`
39
+ (`'onprem' | 'cloud' | 'basis740'`), `IAdtTypeTables`, `AdtApi<V>`,
40
+ `AdtTypeCode`, `AdtTypeCodeOf<V>`, `AdtApiWith<V, Op>` and
41
+ `AdtApiWithIn<T, Op>` (the APIs one code of which performs every operation
42
+ of `Op` — operations spread across two codes do not count),
43
+ `AdtTypeCodeWith<V, Op>`, `AdtObjectKind`, `AdtSourceTypeCode`,
44
+ `AdtParentedTypeCode`.
45
+ - `IAdtAnsweredObject`: `{ type: AdtTypeCode }` or `{ unknownType: string }`,
46
+ exclusive — what a code read from an answer is, so an unknown one reaches the
47
+ consumer as the text ADT sent rather than being dropped.
48
+ - `AdtObjectIdentity<TConfig, TParent>`: what an identifying member takes —
49
+ `Partial<TConfig>` itself when `TParent` is `never`, otherwise every field
50
+ optional but `TParent`, which is required.
51
+
52
+ ### Changed (breaking)
53
+
54
+ - **The identifying atoms take the parent's field as a last type parameter,**
55
+ `TParent extends keyof TConfig = never`: `IAdtReadable`,
56
+ `IAdtMetadataReadable`, `IAdtEnhancementHost`, `IAdtIncludeEnhancementHost`,
57
+ `IAdtDeletable` (after `TChecked`), `IAdtValidatable`, `IAdtCheckable`,
58
+ `IAdtActivatable`, `IAdtLockable`, `IAdtVersionable`, `IAdtTransportAware`.
59
+ Their `config` is `AdtObjectIdentity<TConfig, TParent>`. With the default it
60
+ is `Partial<TConfig>` — the same type as before, so an existing contract and
61
+ code generic in `TConfig` compile unchanged. A contract whose API has a
62
+ parent passes its field: `functionGroupName` for a function module and a
63
+ function include, `className` for the four local class includes and for a
64
+ message class message; its identifying members then require it.
65
+ - **`IObjectReference` is generic in its code,**
66
+ `IObjectReference<C extends AdtTypeCode = AdtTypeCode>`: `type` is `C`, and
67
+ `parentName` is required when `[C] extends [AdtParentedTypeCode]` —
68
+ `IObjectReference<'FUGR/FF'>` needs it — and optional otherwise, the default
69
+ included. The condition is not distributive: a reference built from a code
70
+ typed `AdtTypeCode` compiles, and an interface can extend `IObjectReference`
71
+ (a union of one member per code exceeds TypeScript's 25 combinations and
72
+ cannot be extended). The group operations take `IObjectReference[]`, so a
73
+ caller that wants the parent enforced types its references by code.
74
+ - **Every code parameter is a code of the tables:**
75
+ - `IAdtObjectAccess`: `readObjectSource` and `getObjectSourceUri` take an
76
+ `AdtSourceTypeCode` (the codes the library reads a source of);
77
+ `readObjectMetadata` and `supportsSourceCode` an `AdtTypeCode` (any
78
+ object has metadata, and asking whether a code has source is asked of any
79
+ code).
80
+ - `IAdtRepositoryStructure.fetchNodeStructure(parentType)` and
81
+ `getObjectStructure(objectType)` take an `AdtTypeCode`: the node and
82
+ object structures are asked of any object — a package's contents, a
83
+ class's includes, a program's parts — so no narrower set is stated.
84
+ - `IGetWhereUsedScopeParams.object_type` and `IGetWhereUsedParams.object_type`
85
+ are an `AdtTypeCode`: where-used is asked of any object.
86
+ - `ISearchObjectsParams.objectType` is an `AdtTypeCode`: the search filters
87
+ by any code.
88
+
89
+ ### Removed (breaking)
90
+
91
+ - `AdtObjectTypeLower`, `AdtObjectType`, `AdtSourceObjectTypeLower` and
92
+ `AdtSourceObjectType`. With them go the codes no release lists, which no
93
+ table holds: `INTF/IF`, `STRU/DT`, `STRU/DS`, `TTYP/DF`, `TTYP/TT`,
94
+ `TTYP/ST`, `DOMA/DM`, `BDEF/BD`, `BIMP/BIM`, `BIMP/`, `BIMPL/`, `FUGR/FC`,
95
+ `FUNC`, bare `SCGR`, `DSFD/DSF`, `DSFI/DSF`, `SUSO/O`, the bare `FUGR` and
96
+ `DTEL`, the lower-case spellings and the friendly names.
97
+
98
+ ### Known library defects, entered as served
99
+
100
+ The tables declare what the library sends, so two members that send a request
101
+ known or inferred to fail are entered as served rather than hidden:
102
+
103
+ - `transformation` `validate` posts to `/sap/bc/adt/xslt/validation`, which
104
+ answers `404` — a known-wrong address.
105
+ - `enhancement` `versions` for `ENHO/XHB` and `ENHS/XSB` addresses
106
+ `…/source/main/versions`, which these source-less codes lack — an inferred
107
+ `404`, unmeasured.
108
+
109
+ ### Migration
110
+
111
+ - Replace `AdtObjectType` with `AdtTypeCode` and `AdtSourceObjectType` with
112
+ `AdtSourceTypeCode` — or `AdtTypeCodeOf<V>` / `AdtTypeCodeWith<V, 'source'>`
113
+ where the variant is known — and pass upper-case codes: `'CLAS/OC'` for
114
+ `'class'`, `'FUGR/FF'` for `'functionmodule'`, `'DDLS/DF'` for `'view'`.
115
+ - Replace each dropped code with the one the releases list: `INTF/IF` →
116
+ `INTF/OI`; `STRU/DT`, `STRU/DS` → `TABL/DS`; `DOMA/DM` → `DOMA/DD`;
117
+ `BDEF/BD` → `BDEF/BDO`; `BIMP/BIM`, `BIMP/`, `BIMPL/` → `CLAS/OC`;
118
+ `DSFD/DSF` → `DSFD/SCF`; `DSFI/DSF` → `DSFI/SFI`; `SUSO/O` → `AUTH`;
119
+ `FUNC` → `FUGR/FF` for a module, `FUGR/F` for a group; `FUGR/FC` and `SCGR`
120
+ have no replacement the library serves.
121
+ - `TTYP/DF`, `TTYP/TT` and `TTYP/ST` become `TTYP/DA` **where any code is
122
+ taken** — `readObjectMetadata`, `supportsSourceCode`, a reference, a
123
+ where-used or search parameter. A table type has no source: `TTYP/DA` is no
124
+ `AdtSourceTypeCode`, so a `readObjectSource` or `getObjectSourceUri` call
125
+ on a table type has no replacement and goes — read its document with
126
+ `readObjectMetadata`.
127
+ - A contract whose API has a parent passes its field to the identifying atoms
128
+ — `IAdtReadable<IFunctionModuleConfig, R, 'functionGroupName'>` — and a
129
+ caller then names it. An `IObjectReference<'FUGR/FF'>` or
130
+ `IObjectReference<'FUGR/I'>` names `parentName`.
131
+ - Type a result's code read from an answer as `IAdtAnsweredObject`, and handle
132
+ `unknownType`.
133
+ - An implementation that declares `(config: Partial<TConfig>, …)` still
134
+ satisfies every atom; nothing an implementation sends changes.
135
+
10
136
  ## [20.2.0] - 2026-10-24
11
137
 
12
138
  ### Added
package/README.md CHANGED
@@ -5,12 +5,13 @@ ADT contracts: object operations, runtime analysis, execution, feeds and service
5
5
  ## TL;DR
6
6
 
7
7
  - **Only ADT.** The test is who imports this package: `@mcp-abap-adt/adt-clients` and whatever replaces its objects, and nobody else. Measured against every repository in development before 11.0.0 — the only others reaching in were `gcts-client` and `cloud-llm-hub`, for `IAbapConnection`, `IAbapRequestOptions` and `IAdtResponse`. Since 11.0.0 the first two come from `interfaces-adt-connection`; `IAdtResponse` is still here.
8
- - What it holds: ADT object operations for 31 object types, runtime analysis, execution, feeds, service bindings, `IAdtResponse` and the error codes. **The ABAP connection** — `IAbapConnection`, `IAdtWireResponse`, its capability atoms, `ITimeoutConfig` — is [`interfaces-adt-connection`](../interfaces-adt-connection) since 11.0.0, and is not re-exported here.
8
+ - What it holds: ADT object operations for 31 object types, the ADT type tables per release variant, runtime analysis, execution, feeds, service bindings, `IAdtResponse` and the error codes. **The ABAP connection** — `IAbapConnection`, `IAdtWireResponse`, its capability atoms, `ITimeoutConfig` — is [`interfaces-adt-connection`](../interfaces-adt-connection) since 11.0.0, and is not re-exported here.
9
9
  - **What left, and where.** Every HTTP header name, the HTTP frame and `HttpError` → [`interfaces-network`](../interfaces-network). Cloud ALM → [`interfaces-calm`](../interfaces-calm). `XmlNode` → [`interfaces-utils`](../interfaces-utils). Authentication in general — credentials, OAuth grants, tokens, interactive login, SAML assertions, `AUTH_TYPE_JWT`/`BASIC` → [`interfaces-auth`](../interfaces-auth). Everything naming SAP or BTP — `ISapConfig`, `SapAuthType`, `SapConnectionType`, `IConfig`, `IConnectionConfig`, `IAuthorizationConfig`, `ICertificateMaterialLoader`, `IServiceKeyStore`, `ISessionStore`, `ITokenProviderResult`, the two validation results and `AUTH_TYPE_XSUAA` with its union → [`interfaces-auth-sap`](../interfaces-auth-sap). Of those, `IConfig`, `IConnectionConfig`, `IServiceKeyStore`, `ISessionStore` and `ITokenProviderResult` moved on to [`interfaces-auth-broker`](../interfaces-auth-broker) in `interfaces-auth-sap` 2.0.0. `ISessionState` and `ISessionStorage` are deleted, not moved.
10
10
  - `IAdtWireResponse` extends `IHttpWireResponse` from `-network` and keeps the headers ADT sends (`sap-adt-location`, both spellings of `content-location`). It lives in `interfaces-adt-connection` since 11.0.0, name and shape unchanged.
11
11
  - Since 14.0.0 `IDebuggerIdentity` is a union by `debuggingMode` (required), `attach` takes the identity, `condition` is for line breakpoints only, and `IAbapDebugger` gains `TSettings` and five members. The CHANGELOG has the migration note.
12
12
  - Since 15.0.0 `skipCount` is gone from breakpoints (the server ignores it) and `clientId` pairs an answer row with its request. The CHANGELOG has the migration note.
13
13
  - Since 15.1.0 the plain class and program run take `debuggee` (`IDebuggeeIds`): the terminal id and IDE id a terminal-mode listener catches the run by.
14
+ - Since 21.0.0 the object type codes are the library's own tables — `ADT_TYPES_ONPREM` (S/4HANA 2025), `ADT_TYPES_CLOUD` (ABAP cloud), `ADT_TYPES_BASIS_740` (SAP_BASIS 7.40 SP04), keyed by API — and every code in a contract is an `AdtTypeCode` drawn from them. `AdtObjectTypeLower`, `AdtObjectType`, `AdtSourceObjectTypeLower` and `AdtSourceObjectType` are removed, and with them the codes no release lists. An identifying atom takes the parent's field as its last type parameter (`TParent`, default `never`, which leaves the config `Partial<TConfig>` as before), and `IObjectReference<C>` requires `parentName` for a code with a parent. A code read from an answer is an `IAdtAnsweredObject`. See "The ADT type tables" and "Migrating to 21.0.0".
14
15
  - Since 20.2.0 every object's result-set contract (`IClassResults`, `IProgramResults`, … 30 in all, `IMessageClassMessageResults<TRead, TWritten, TDeleted>` among them) and `IServiceBindingPublicationConfig` are declared here, in the object's own `IAdtX.ts`: the slot map an implementation is constructed with, each slot an `IResultStrategy<unknown>`. A consumer composes its client contract from these and the atoms. Additions only.
15
16
  - Since 20.1.0 `IAdtObjectProperties` reads one repository object's properties from `/informationsystem/objectproperties/values?uri=`, any object uri (a transaction by its `vit` workbench uri); its own atom, not part of `IAdtInformationSystem`.
16
17
  - Since 20.0.0 `IAdtClientOptions` has no `enableAcceptCorrection`: correcting a refused format is the consumer's own. See "Migrating to 20.0.0".
@@ -30,26 +31,140 @@ npm install @mcp-abap-adt/interfaces-adt
30
31
 
31
32
  | directory | files | what |
32
33
  |---|---|---|
33
- | `adt/` | 39 | the object contracts: capability atoms, the object types, `IAdtResponse`, `IAdtError`, the error codes, the transport request's object list |
34
+ | `adt/` | 41 | the object contracts: capability atoms, the object types, the ADT type tables and their entry shape, `IAdtResponse`, `IAdtError`, the error codes, the transport request's object list |
34
35
  | `runtime/` | 14 | runtime analysis: the debuggers (`IAbapDebugger`, `IAmdpDebugger`) and `IMemorySnapshots`, `IProfiler`, the trace contracts (`ITraceListing`/`ITraceReading`, `ICrossTrace`, `ISt05Trace`), `IApplicationLog`, `IAtcLog` and the ATC run (`IAtcRunOptions`, `IAtcFindings`), `IDdicActivation`, `IGatewayErrorLog`, `IRuntimeDumps`, `ISystemMessages` |
35
36
  | `execution/` | 3 | class and program execution, with profiling |
36
37
  | `feeds/` | 2 | the ADT feed contracts |
37
38
  | `service/` | 1 | service definitions and bindings |
38
39
  | `shared/` | 1 | what more than one object type needs |
39
40
 
40
- Six directories, all ADT. `connection/` left for `interfaces-adt-connection` in 11.0.0. `sap/`, `auth/`, `token/`, `session/`, `serviceKey/`, `store/`, `validation/` and `Headers.ts` were here until 9.0.0 and are listed above under what left; `__typechecks__/` holds 24 files that compile shapes this contract must and must not accept, and ships in no tarball.
41
+ Six directories, all ADT. `connection/` left for `interfaces-adt-connection` in 11.0.0. `sap/`, `auth/`, `token/`, `session/`, `serviceKey/`, `store/`, `validation/` and `Headers.ts` were here until 9.0.0 and are listed above under what left; `__typechecks__/` holds 29 files that compile shapes this contract must and must not accept, and ships in no tarball.
41
42
 
42
43
  The contract rules — what a member answers, how a strategy is supplied, how a contract is built — are in [`docs/architecture/ARCHITECTURE.md`](../../docs/architecture/ARCHITECTURE.md). Domain-by-domain documentation with examples used to sit in the facade's README; the facade is deleted, and each package documents its own contracts.
43
44
 
44
45
  **There is no facade to stay compatible with.** It was pinned to its 44.0.0 surface in both directions — nothing from that release could disappear from it and nothing could appear without being written down — and `tools/check-surface.js`, `surface-44.0.0.txt`, `baseline-44.0.0.json` and `surface-added.txt` existed to enforce exactly that. The facade is deleted in its 52.0.0 (decision 34), so the property is gone along with the files that proved it; git holds them. What `check-surface.js` still asks is the half that never depended on it: is each symbol declared in the package `tools/package-map.json` assigns it to.
45
46
 
47
+ ## The ADT type tables
48
+
49
+ What the library serves, per release variant, is declared here as three `as
50
+ const` tables — constants, written by hand:
51
+
52
+ | table | variant | release |
53
+ |---|---|---|
54
+ | `ADT_TYPES_ONPREM` | `'onprem'` | S/4HANA 2025 on-premise |
55
+ | `ADT_TYPES_CLOUD` | `'cloud'` | ABAP cloud |
56
+ | `ADT_TYPES_BASIS_740` | `'basis740'` | SAP_BASIS 7.40 SP04 |
57
+
58
+ **Keyed by API, not by code.** The key is the client's factory name (`class`
59
+ for `getClass()`, `functionModule`, `request` for `getRequest()`), because one
60
+ code serves two APIs (`CLAS/OC`: `class` and `behaviorImplementation`;
61
+ `TABL/DS`: `structure` and `appendStructure`) and one API several codes
62
+ (`enhancement`: `ENHO/XHH`, `ENHO/XHB`, `ENHS/XSB`). An entry holds:
63
+
64
+ - `kind` — the object's kind in the tools' one vocabulary (`function_module`);
65
+ two APIs on one code share it;
66
+ - `collection` — the ADT collection its resource lives in, the parent's for an
67
+ API addressed under a parent;
68
+ - `codes` — for each code: `parent` (the parent API, or `null`),
69
+ `nameMaxLength`, `operations` and `evidence`, the corpus case of the
70
+ release's `typestructure` answer that lists the code
71
+ (`system-description-basis-740--07-typestructure`); and, where a code lives
72
+ elsewhere than its API, its own `collection` — the enhancement codes under
73
+ `/sap/bc/adt/enhancements/enhoxhh`, `/enhoxhb` and `/enhsxsb`.
74
+
75
+ The local class includes and the transport request have no code the library
76
+ sends: their entries have `codes: {}`, and their `parent`, `operations` and
77
+ `evidence` on the entry — the case that lists the parent's code, or for the
78
+ request the release's `typestructure` case. A coded entry names at least one
79
+ code: `IAdtTypeTables` takes each table as `AdtCheckedTable<T>`, which refuses
80
+ an empty `codes` that `satisfies` cannot see.
81
+
82
+ **Operations** come from one closed vocabulary, `AdtOperation`: `create`,
83
+ `read`, `source`, `readMetadata`, `update`, `updateMetadata`, `lock`,
84
+ `unlock`, `activate`, `check`, `validate`, `versions`, `deletionCheck`,
85
+ `delete`, `transport`; the families of one API (`readEnhancementElements`,
86
+ `readEnhancementOptions`, `activateTestClasses`, `checkCdsTestDoubles`, the
87
+ feature toggle's `switchOn`, `switchOff`, `getRuntimeState`, `checkState`, the
88
+ service binding's `getServiceBindingTypes`, `getServiceGroup`, the transport
89
+ request's `list` … `changeTaskType`); `run` and `profile` for the executors;
90
+ and `unitTestRun`, `unitTestRunSync`, `unitTestStatus`, `unitTestResult` for
91
+ the ABAP Unit runners' four members, which 7.40 serves apart. `source` says the object has a source the
92
+ library reads; `AdtSourceTypeCode` is drawn from it.
93
+
94
+ **What is not in a table is not served.** An API whose every member the 7.40
95
+ client refuses is absent from `ADT_TYPES_BASIS_740`, and an operation it
96
+ refuses is absent from its code — 7.40 has no `deletionCheck`, no `transport`,
97
+ no `run`. The entry shape (`AdtApiTable<R>`) refuses a misspelt field, an
98
+ operation outside the vocabulary, an API with no factory and another release's
99
+ evidence at compile time.
100
+
101
+ **Derived types**, all from the tables:
102
+
103
+ | type | what |
104
+ |---|---|
105
+ | `AdtVariant` | `'onprem' \| 'cloud' \| 'basis740'` |
106
+ | `AdtApi<V>` | the APIs of variant `V` |
107
+ | `AdtTypeCode` | every code of any table |
108
+ | `AdtTypeCodeOf<V>` | the codes of variant `V` |
109
+ | `AdtApiWith<V, Op>` | the APIs of `V` one code of which performs every operation of `Op` (`AdtApiWithIn<T, Op>` over any table) |
110
+ | `AdtTypeCodeWith<V, Op>` | the codes of `V` whose facts list `Op` |
111
+ | `AdtObjectKind` | every kind |
112
+ | `AdtSourceTypeCode` | the codes with `source` |
113
+ | `AdtParentedTypeCode` | the codes with a parent API: `FUGR/FF`, `FUGR/I` |
114
+
115
+ A map a consumer keeps over the codes is typed by them, and the compiler then
116
+ asks for every code and refuses any other:
117
+
118
+ ```ts
119
+ const label: { readonly [C in AdtTypeCode]: string } = { 'CLAS/OC': 'Class', /* … every code */ };
120
+ ```
121
+
122
+ **Proved against the systems elsewhere.** This package holds no code, so it
123
+ holds no test against the releases: the conformance check in
124
+ `@mcp-abap-adt/adt-clients` reads each release's recorded `typestructure`,
125
+ `discovery` and, on the newer releases, `urimapper` answers. It fails on a code
126
+ not listed, a parent or a name length that disagrees, a collection not
127
+ advertised, and an address built for a sample object that differs from the
128
+ `urimapper` answer for it. It holds the capabilities too: `run` on a code that
129
+ does not list `EXECUTE`, or `profile` without `PROFILE`, is a conflict; a
130
+ `create` on a code without `CREATE` is listed apart, since ADT creates those
131
+ through their own collection; and a code listing `CREATE` that no entry
132
+ creates goes into the coverage. `src/__typechecks__/` holds the tables
133
+ recorded cell for cell — per variant, API and code, the parent and the exact
134
+ set of operations — as an exact equality, so a table edit is made twice, on
135
+ purpose.
136
+
137
+ **An answered code.** A code read from an ADT answer is an
138
+ `IAdtAnsweredObject`: `{ type: AdtTypeCode }` when the tables know it,
139
+ `{ unknownType: string }` with the text as sent when they do not. The two are
140
+ exclusive.
141
+
142
+ **Parents.** The atoms that identify an object take the parent's field as
143
+ their last type parameter, `TParent extends keyof TConfig = never`, and their
144
+ `config` is `AdtObjectIdentity<TConfig, TParent>`: with `never` that is
145
+ `Partial<TConfig>` itself — the same type as before 21.0.0, so a contract
146
+ written then, or code generic in `TConfig`, is unchanged — and otherwise every
147
+ field optional but `TParent`, which is required. A contract whose API has a
148
+ parent passes it: `functionGroupName` for a function module and a function
149
+ include, `className` for a local class include and a message class message.
150
+
151
+ ```ts
152
+ type ModuleRead = IAdtReadable<IFunctionModuleConfig, string, 'functionGroupName'>;
153
+ // read({ functionModuleName }) does not compile; read({ functionGroupName, functionModuleName }) does
154
+ ```
155
+
156
+ `IObjectReference<C extends AdtTypeCode = AdtTypeCode>` requires `parentName`
157
+ when `[C] extends [AdtParentedTypeCode]` — `IObjectReference<'FUGR/FF'>` —
158
+ and leaves it optional otherwise, the default included, so a reference built
159
+ from a code typed `AdtTypeCode` compiles and an interface can extend it.
160
+
46
161
  ## Enhancements and their hosts
47
162
 
48
163
  `EnhancementType` accepts `enhoxhb` (BAdI implementation, ENHO/XHB), `enhoxhh`
49
164
  (source code plugin, ENHO/XHH), and `enhsxsb` (BAdI enhancement spot, ENHS/XSB).
50
165
  The ABAP Cloud trial refuses the `enhoxhh` collection (403 on create and read;
51
166
  no content type in its discovery). Class enhancements (`enhoxh`) and plain
52
- spots (`enhsxs`) answered 500 on reads on E19 (2026-10-15) and on premise +
167
+ spots (`enhsxs`) answered 500 on reads on S/4HANA on-premise (2026-10-15) and on premise +
53
168
  trial in mcp-abap-adt `5046d8a6` (2026-10-02), which also measured Eclipse
54
169
  opening them in SAP GUI. The trial discovery lists no content type for either.
55
170
  Callers migrating from 16.0 must remove those calls; the removed subtypes now
@@ -70,7 +185,7 @@ names used to create plugins.
70
185
  atom for an include's elements and options, with the same two members. Both
71
186
  reads take optional `context` naming the include's main program (`SAPLSVIM`
72
187
  for an include of function group SVIM). Without it, both reads answered 400
73
- ED/258 "No main program for include … found" (E19, 2026-10-15). Context stays
188
+ ED/258 "No main program for include … found" (S/4HANA on-premise, 2026-10-15). Context stays
74
189
  optional because an include with a single main program is unmeasured.
75
190
  Both atoms accept per-call `analyse` and return `IAdtResponse`.
76
191
 
@@ -116,6 +231,51 @@ The field is on each member's own options, not on `IAdtAnalyseOptions` or
116
231
  `IAdtOperationOptions`. `src/__typechecks__/headersOnEveryMember.ts` holds this
117
232
  for every member and every overload.
118
233
 
234
+ ## Migrating to 21.0.0
235
+
236
+ Every break is a type error; nothing a correct call sends changes.
237
+
238
+ - **The four unions are gone.** Replace `AdtObjectType` with `AdtTypeCode` and
239
+ `AdtSourceObjectType` with `AdtSourceTypeCode`, or with the variant's own
240
+ `AdtTypeCodeOf<V>` / `AdtTypeCodeWith<V, 'source'>` where the variant is
241
+ known. The lower-case spellings and the friendly names (`'class'`,
242
+ `'functionmodule'`, `'view'`, …) are no codes: pass the upper-case code
243
+ (`'CLAS/OC'`, `'FUGR/FF'`, `'DDLS/DF'`).
244
+ - **The codes no release lists do not compile.** `INTF/IF` is `INTF/OI`;
245
+ `STRU/DT` and `STRU/DS` are `TABL/DS`; `DOMA/DM` is `DOMA/DD`; `BDEF/BD` is
246
+ `BDEF/BDO`; `BIMP/BIM`, `BIMP/` and `BIMPL/` are `CLAS/OC`; `DSFD/DSF` is
247
+ `DSFD/SCF`, `DSFI/DSF` is `DSFI/SFI`, `SUSO/O` is `AUTH`; a function module
248
+ is `FUGR/FF` and a function group `FUGR/F`, so `FUNC` and `FUGR/FC` go; bare
249
+ `SCGR` and the other bare codes (`FUGR`, `DTEL`) are none — `AUTH` is the
250
+ one bare code a table holds.
251
+ - **A table type is `TTYP/DA` where any code is taken.** `TTYP/DF`, `TTYP/TT`
252
+ and `TTYP/ST` become `TTYP/DA` in `readObjectMetadata`, `supportsSourceCode`,
253
+ a reference, a where-used or a search parameter. A table type has no source,
254
+ so `TTYP/DA` is no `AdtSourceTypeCode`: a `readObjectSource` or
255
+ `getObjectSourceUri` of a table type has no replacement — read its document
256
+ with `readObjectMetadata`.
257
+ - **Every code parameter takes these codes:** `IObjectReference.type`,
258
+ `readObjectSource`, `getObjectSourceUri` (`AdtSourceTypeCode`),
259
+ `readObjectMetadata`, `supportsSourceCode`, `fetchNodeStructure`'s
260
+ `parentType`, `getObjectStructure`'s `objectType`, the where-used
261
+ parameters' `object_type` and `ISearchObjectsParams.objectType`
262
+ (`AdtTypeCode`).
263
+ - **A parent is named by the contract.** A contract composing the identifying
264
+ atoms for a function module or a function include passes
265
+ `'functionGroupName'` as their `TParent`, for a local class include or a
266
+ message class message `'className'`; a caller of that contract then names
267
+ the parent. A contract that passes nothing is unchanged. An
268
+ `IObjectReference<'FUGR/FF'>` or `IObjectReference<'FUGR/I'>` names
269
+ `parentName`.
270
+ - **An implementation** declaring an identifying member as
271
+ `(config: Partial<TConfig>, …)` still satisfies the atom — it accepts more.
272
+ - **A result** that carries a code read from an answer is typed
273
+ `IAdtAnsweredObject`: switch on `type`, and handle `unknownType` for a code
274
+ the tables do not hold.
275
+ - **The tables are new.** `ADT_TYPES_ONPREM`, `ADT_TYPES_CLOUD`,
276
+ `ADT_TYPES_BASIS_740` and the types derived from them are additions; see "The
277
+ ADT type tables".
278
+
119
279
  ## Migrating to 20.0.0
120
280
 
121
281
  `IAdtClientOptions.enableAcceptCorrection` is removed, so code that sets it