Files
alexzandClaude Opus 5 ffd33f4ec0 ADR-004: back out of on-stack RAP; retarget to starter customizing tenant
Both tenants belong to the same starter system: my429480 is its
customizing tenant (client 100, key-user extensibility only, no ABAP)
and my431353 is its development tenant (client 080). This package had
recorded my429480 as "productive" and ADR-002 had assumed it offered
developer extensibility; both were wrong.

- ADR-004 withdraws the on-stack RAP route and moves the application to
  a side-by-side runtime against released OData APIs. ADR-002 marked
  superseded.
- Development tenant my431353 parked: all 19 ZARENA_PLM objects left
  active, sources kept in docs/handover/rap/ as reference, so the route
  stays reversible.
- Replacement host left open as OQ-11 (key-user extensibility vs CAP
  side-by-side); recommendation recorded as CAP. No build starts until
  OQ-11 is closed.
- RAP-dependent items V-2, V-3, OQ-5, OQ-8, OQ-9, OQ-10 parked rather
  than closed.
- Tenant references corrected across CLAUDE.md, KNOWLEDGE.md,
  app/README.md, the RAP handover README, the rap-developer agent and
  the reentrance-login helper README.

No SAP tenant was modified.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-29 10:33:29 -07:00

398 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# KNOWLEDGE — tombstones & landmines
Carried across the 2026-09-04 knowledge bankruptcy from the working Express
predecessor. Filter applied: an item was kept only if it (a) cannot be
re-derived from code or a live query, AND (b) is expensive or harmful to
re-learn. Everything else was deliberately left behind to be re-derived from
ground truth. Every entry is dated; re-verify on first POC contact. Add new
entries the same way — dated and falsifiable.
**Tenant note (2026-09-29).** Both tenants named below are tenants of the same
starter system: the customizing tenant `my429480` (client 100, key-user
extensibility and configuration only) and the development tenant `my431353`
(client 080, developer extensibility). The development tenant is **parked as of
2026-09-29** and its objects are left in place, so every `my431353` entry here is
a historical finding from the client 080 track, not a statement about the current
working target. The working target is `my429480`.
## SAP S/4HANA (starter system customizing tenant `my429480`, client 100, Public Cloud, API-only)
- [2026-09-04, verified by predecessor in live use] **BOM items must be POSTed
sequentially** after the header POST. Parallel item POSTs fail SAP's
consistency check.
- [2026-09-04, same] **`AvailabilityCheckType` is not exposed in the Product
API V4** — requires the V2 `API_PRODUCT_SRV` fallback for that one field.
- [2026-09-04, same] **BOM read works only on the v1 service**;
`API_BILL_OF_MATERIAL_SRV;v=0002` rejects guid key lookups. Writes go to
`;v=0002`.
- [2026-09-04, same] OData V2 date format is `/Date(ms)/`; the "end of time"
value (9999-12-31) is `/Date(253402214400000)/`.
- [2026-09-04, same] **Idempotency pattern that works: SAP is the ledger.** The
Arena ECO number is stamped into `ReasonForChangeText`; no local sync-state
database is needed or wanted.
- [2026-09-10, predecessor code read] **BOM header create must use
`EngineeringChangeDocForEdit`** — `EngineeringChangeDocument` is
`sap:creatable=false` and silently dropped. ECM BOM items must carry
`HeaderChangeDocument` = the header's change number or SAP answers "Input
parameters are initial". (arena-plm.js:785-846)
- [2026-09-10, same] **`A_ChangeMasterObjTypeAssgmt` POST requires
`IsActiveForChangeNumber: true`** — without it SAP returns 201 and silently
discards the row. (arena-plm.js:914-924)
- [2026-09-10, same] **ProductDescription updates: PATCH by full key**
(`Product=…,Language='EN'`); PATCH via the nav property returns HTTP 501;
fall back to POST on 404/405. (arena-plm.js:1411-1414)
- [2026-09-10, same] `ProcurementType` can only be written together with
`MRPType` in the same `ProductPlantSupplyPlanning` PATCH.
(arena-plm.js:1623-1640)
## Arena PLM API (`api.arenasolutions.com/v1`)
- [2026-09-04, same] Session auth: `POST /login` → `arenaSessionId`, ~25-minute
TTL. Concurrent logins race — serialize login behind a promise lock and
re-login automatically on 401.
- [2026-09-10, predecessor code read] **WORKING-revision overlay is
load-bearing**: the seven SAP classification attributes (SAP Product Type,
SAP Plant, …) are writable only on the WORKING revision (Arena error 3224),
while `/items?number=` resolves the EFFECTIVE revision — merge those
attributes from WORKING over EFFECTIVE, and treat overlay failure as fatal
(the predecessor's best-effort overlay silently turned valid items into
NO_PRODUCT_TYPE errors). (arena-plm.js:508-552)
- [2026-09-10, same] `/items/{guid}/changes` does not exist (404) — derive the
ECO from `/items/{guid}/revisions`, first EFFECTIVE revision with
`change.number`. (arena-plm.js:1799-1806)
- [2026-09-10, same] The `/changes` feed has **no working server-side date
filter** — delta detection must filter client-side (the predecessor pages
the whole feed, O(history)). The outbound-integration queue
(`/outboundintegrations/{guid}/events`, `reconciled` flag as a cursor held
by Arena) is the clean delta mechanism. (arena-plm.js:1117-1263)
## Toolchain (worker)
- [2026-09-10, npm registry] **TypeScript `latest` is the 7.x native-compiler
major** (no stable 6.x; only `6.0.0-beta`). typescript-eslint 8.70.0
declares peer `typescript >=4.8.4 <6.1.0`, silently forcing the 5.9.x line —
the worker pins `~5.9.3`. Falsifiable: recheck
`npm view typescript-eslint peerDependencies` before any TS bump.
- [2026-09-10, npm registry] **`@types/node` `latest` dist-tag points at
22.x** while 24.x/26.x lines exist — an unpinned install silently targets
Node 22 types. Pin the major (`^24`) to match the runtime.
## Landmines
- [2026-09-15] **abapGit is not a prerequisite for SAP's ADT for VS Code.** The
`sapse.adt-vscode` extension talks ADT/HTTP to the tenant and ships no git or
abapGit commands (extension 1.1.2 `package.json`/readme, verified 2026-09-15).
The "abapGit must be set up in the ABAP system" idea comes from the community
extension `murbani.vscode-abap-remote-fs` (installed on this host), whose
abapGit commands need the open-source `ZABAPGIT` report in the backend — which
cannot be installed in a Public Cloud tenant. In ABAP Cloud, abapGit exists
only as SAP's supported fork behind the **Eclipse** ADT plug-in
(`https://eclipse.abapgit.org/updatesite/`, "abapGit Repositories" view); no
VS Code variant exists [source: sap-docs sap-help loio
2002380aeda84875a5fae4adc66b3fdb; /btp-cloud-platform/30-development/
import-content-from-abapgit-repository-into-the-abap-environment-0b0d894;
https://github.com/abapGit/ADT_Frontend, verified 2026-09-15]. It imports
released object types only, from an internet-reachable repository (no Cloud
Connector), into a chosen package/transport.
- [2026-09-15] **ADT MCP `x-ui-service` generator quirks (my431353, ADT VS
Code 1.1.2):** every field needs `semanticType` (else "Builtin type of
field is invalid"); it prepends its own `Z` to your prefix and appends
`000` even with an empty suffix (`Z` + `ARENA_CHANGE_APPROVAL` →
`ZZUI_ARENA_CHANGE_APPRVL000_O4`), names SRVD and SRVB identically, and
the schema's `required` lists a non-existent `businessEntity` key — omit
it. `get_schema` session ids are single-use. It returns only the SRVB URI;
other object URIs follow `abap:/repotree-v1/<dest>/System Library/ZLOCAL/<pkg>/…`
with extensions `.tabl.json`, `.ddls.acds`, `.bdef.json`, `.ddlx.acds`,
`.dcls.acds`, `.clas.abap`, `.srvd.acds`, `.srvb.json`, `.ront.json`,
`.nont.json`. `create_object` for SRVD needs `"sourceType":"S"`; BDEF and
SRVB creation validate the referenced object's ACTIVE version, so create
and activate DDLS/SRVD sources first. ATC via MCP rejects RONT/NONT.
- [2026-09-16] **An expired VS Code ADT logon shows up in the ADT MCP only as
"Your user was logged off."** `abap_list_destinations` still lists the
destination and `get_object_type_details` still returns field metadata,
so neither proves a live session. **ADT for VS Code logs on to S/4HANA
Cloud with a reentrance ticket and a localhost redirect:** it opens
`https://<tenant>/sap/bc/adt/core/http/reentranceticket?redirect-url=http://localhost:<port>/adt/redirect`,
and after SSO the tenant redirects to
`http://localhost:<port>/adt/redirect?…&reentrance-ticket=<ticket>`
(observed 2026-09-16). The ticket in that URL is a live logon credential:
never paste it into chats, logs or files. The same mechanism is the
plausible browser-free login path for `abap-adt-mcp` (OQ-9). **Tested
2026-09-18: it does not work.** With a freshly captured reentrance
ticket, `https://my431353.s4hana.cloud.sap/sap/bc/adt/core/discovery`
and an ABAP class source URL answered HTTP 200 with the same 3094-byte
SAML redirect page (`SAMLRequest`, `saml2`) for all of: `Cookie:
MYSAPSSO2=<ticket>`, header `MYSAPSSO2: <ticket>`, and no credential at
all, with and without `?sap-client=080`. A reentrance ticket is
therefore neither a logon-ticket cookie nor an assertion-ticket header
here; ADT exchanges it some other way. Do not spend more on
`abap-adt-mcp`'s `sso2` mode without first capturing what the extension
actually sends. `abap_creation-run_validation` is the
cheapest read-only liveness check (it answers "… validation failed: Your
user was logged off."). Fix it by logging on to the destination again in
VS Code; the MCP port and token stay the same unless VS Code reloads
(live 2026-09-16, ~1.5 h after the last successful call).
- [2026-09-16] **Ask the ADT MCP for name limits and package existence; do
not guess them.** `abap_creation-get_object_type_details` returns each
type's create fields and `maxLength`: `TABL/DT` 16, while `DDLS/DF`,
`SRVD/SRV`, `SRVB/SVB` and `BDEF/BDO` allow 30 (the generator's `APPRVL`
truncation came from that 30 limit). `abap_creation-run_validation` is a
read-only way to check that a package exists: a missing package answers
"Package '<name>' does not exist" [source: adt-mcp on 0M7DEJI, verified
2026-09-16]. The Claude Code session does not expose the adt-mcp tools
unless the server was up at session start. A JSON-RPC probe over
`http://127.0.0.1:2236/mcp` with the `.mcp.json` bearer token works for
read-only checks in the meantime.
- [2026-09-16] **In the VS Code ADT workspace, the `.json` file in an object
folder is header metadata, never the source.** A table folder holds
`zchangeapproval.tabl.json` (formatVersion, description, originalLanguage,
`abapLanguageVersion`) and `zchangeapproval.tabl.ddic` (the Dictionary DDL
source). Paste into `.ddic`, and activate through the `.tabl.ddic` URI
(live, "Activation successful."). For objects created with
`create_object`, the returned `filePath` names the source file: DDLS
`.ddls.acds`, DCLS `.dcls.acds`, BDEF **`.bdef.abdl`** [source: adt-mcp
abap_creation-create_object / abap_activate_objects on 0M7DEJI, verified
2026-09-16]. The `.tabl.json` / `.bdef.json` activation URIs recorded on
2026-09-15 were generator objects; trust the returned `filePath` over
that table. BDEF activation through `.bdef.abdl` is proven (U6, live).
- [2026-09-16] **A managed `strict ( 2 )` BDEF activates before its
behavior pool class exists** (`ZR_CHANGEAPPROVAL`, "Activation
successful.", with no class `ZBP_R_CHANGEAPPROVAL` yet) [source: adt-mcp
abap_activate_objects on 0M7DEJI, verified 2026-09-16]. Once the class
exists, activate BDEF and class together. `abap_activate_objects` returns
only "Activation successful." with no warnings on success. On failure it
lists messages with line and column but no severity (U13 SRVD,
2026-09-16), so read severity in the editor. Service definitions
report "Comments are not supported and will be deleted on save" for a
leading block comment, and **that message blocks activation**: the same SRVD failed with a
19-line `/* */` header and activated without it (live 2026-09-16; the
DCLS, DDLX and BDEF headers did not block). The language allows comments
[source: abap-docs /abap-docs-cloud/ABENCDS_GENERAL_SYNTAX_RULES,
verified 2026-09-16], so this is the tooling. Keep SRVD sources free of
comments. `abap_atc_get_result` returned only totals for a run with 43
infos (UI leg), but per-object `findings[]` (priority, check class,
message id and title, quick-fix flags) for a run with a priority-3
warning (worker leg). Expect details for warnings and errors at least
(both runs live 2026-09-16). A projection BDEF over a view with
`@AccessControl.authorizationCheck: #CHECK` raises SLIN W607 (+BDL 549)
"should be replaced with #MANDATORY" (priority 3; it does not block
activation). An OData V4 **Web API** binding reports
`bindingCategory: "1"` (UI: `"0"`) in `fetch_services`.
- [2026-09-16] **OData V4 identity on a RAP UI service: the binding name is
only the URL's first segment.** For definition `ZUI_ARENA_CHANGE_APPROVAL`
and binding `ZUI_ARENA_CHANGE_APPR_O4`, the live `$metadata` uses
namespace `com.sap.gateway.srvd.zui_arena_change_approval.v0001`, from the
**service definition**, and entity type `ChangeApprovalType`, with a
`Type` suffix and no underscore (live 2026-09-16,
`docs/v2/zui_arena_change_appr_o4.metadata.xml`). The earlier assumption
that the namespace carries the binding name and a `_Type` suffix was
wrong. RAP also emits `__OperationControl` with
`Core.OperationAvailable Path="_it/__OperationControl/<action>"` for
`features : instance` actions, `SAP__Messages`, `Nullable="false"` on
non-key elements, and `cast( case … as abap_boolean preserving type )`
surfaces as `Edm.Boolean` (INT1 literals as `Edm.Byte`, `utclong` as
`Edm.DateTimeOffset Precision="7"`). Copying `$metadata` from Chrome's
XML tree view decodes `&amp;` to `&`; use `view-source:` or re-escape.
- [2026-09-16] **Live RAP `$metadata` works verbatim as Fiori mock metadata**
(`@sap-ux/fe-mockserver-core` 1.7.15 serves it and accepts `$select` on
`__OperationControl/approve`). Mock rows must then carry
`__OperationControl`, or the enablement paths resolve to nothing. The
app's ESLint config checks only TS/JS, so run `npx @ui5/linter` for UI5.
The fiori-mcp `list_functionality` for `app/` offers only
add/delete page and controller extension, so dataSource and annotation
edits are made directly. The cached `@ui5/manifest` 1.89.0 schema
rejects the generator's manifest `_version: "2.11.0"`; that is not a
defect in the app.
- [2026-09-16] **A published custom UI service answers on the UI host, not the
`-api` host, for a business user.** `fetch_service_information` reports
the service URL on `my431353-api.s4hana.cloud.sap` (with
`sap-client=080`), but a browser business-user call there is refused as
"Forbidden / blocked by UCON". The same path on
`my431353.s4hana.cloud.sap` returns `$metadata` for the developer user,
before any IAM app exists (live 2026-09-16). The `-api` host is the
communication-user entry point (communication arrangement), so the
worker's A2X service goes there through a custom communication scenario
(V-2), never the UI service. After publishing, ADT for VS Code reports
"<binding> published locally".
- [2026-09-16] **In ADT for VS Code, publishing a service binding is a code
lens, not a button or a palette command.** Open the binding's `.srvb.json`
source and click the **Publish** code lens; Unpublish and Preview… work the
same way [source: sap-docs sap-help loio dd6f5de63e7245a7abe7e39389841596
"ABAP RAP Tools", verified 2026-09-16]. The extension (1.1.2) contributes
no publish command, and the SAP ADT MCP has no publish tool. `create_object` for a class returns only the global
`.clas.abap` path, no local-types (CCIMP) path.
- [2026-09-16] **`abap-adt-mcp` 2.1.0 auto-detects a browser for SSO only on
macOS.** `detectBrowser()` checks `SAP_BROWSER_PATH` and then three
`/Applications/…` paths; otherwise it throws "No Chrome/Edge/Brave found
for SSO login" (`dist/lib/browserLogin.js:38-50`, read 2026-09-16). On
this Linux host the server env must carry
`SAP_BROWSER_PATH=/usr/bin/google-chrome` along with the desktop display
variables. Login harvests the HttpOnly `MYSAPSSO2`/`SAP_SESSIONID` cookies
over the Chrome DevTools Protocol (`puppeteer-core`). `listSystems` needs
no SAP call and is the safe first probe of its policy. **Its SSO does not
work from a remote shell:** there is no localhost redirect (SAML returns
to the tenant), and the sign-in must be typed into the server-side Chrome
window (`headless: false`, profile
`~/.abap-adt-mcp/sso/<host>`, `--remote-debugging-port=0`, 300 s timeout).
Over multi-hop SSH neither the desktop nor a DevTools relay is reachable in
practice. Do the first sign-in at the server's desktop; with "stay signed
in" later logins should complete unattended (unverified, 2026-09-16).
- [2026-09-16] **Create fields for the remaining RAP types (`get_object_type_details`
on 0M7DEJI):** `CLAS/OC`: packageName, name (≤30), description, optional
superclass, interfaces. `DCLS/DL`: packageName, name (≤30), description,
optional `protectedEntity`. `DDLX/EX`: packageName, name (≤**40**),
description, optional `extendedEntity` [source: adt-mcp
abap_creation-get_object_type_details on 0M7DEJI, verified 2026-09-16].
Pass `protectedEntity` / `extendedEntity` so the editor starts from the
right skeleton. DCLS creation does **not** require the protected entity to
be active. `ZC_CHANGEAPPROVAL_A2X` access control validated and was
created while its DDLS was still empty and never activated (unlike
BDEF/SRVB creation). `SRVB/SVB` `bindingType` values are exactly `OData
V2 - UI`, `OData V2 - Web API`, `OData V4 - UI`, `OData V4 - Web API`,
whatever label the release notes use [source: adt-mcp
abap_creation-run_validation / create_object /
get_object_type_details on 0M7DEJI, verified 2026-09-16].
- [2026-09-16] **Service binding names: SAP Help says 26 characters, the
ADT MCP allows 30.** The 26-character limit appears on the ABAP Cloud,
SAP Cloud Platform and ABAP Platform 2021 "Creating Service Binding"
pages [source: sap-docs sap-help loio 4bad0d7280b742a68dd2d42b1441f09a,
verified 2026-09-16]. `get_object_type_details` reports 30 for
`SRVB/SVB`, and the `x-ui-service` generator itself emits 29–30-character
bindings, which activated unpublished on `my431353` on 2026-09-15.
Whether publishing accepts more than 26 is unknown. Stay at 26 or fewer
rather than find out after a whole BO leg. The generator does not keep to
the documented limit, which is one more reason not to use it for names
that ship.
- [2026-09-16] **In an OData V4 binding URL
`/sap/opu/odata4/sap/<binding>/srvd/sap/<alias>/0001/`, the second
segment is the binding's service name (alias), not necessarily the
service definition name. It can be renamed only while the binding is
unpublished** [source: sap-docs community-14433266 "How to rename an
OData V4 service?", verified 2026-09-16]. Check it before publishing.
- [2026-09-16] **CDS CASE results take the longest branch type, and untyped
integer literals are typed INT1..INT8 by value** [source: abap-docs
/abap-docs-cloud/ABENCDS_CASE_EXPRESSION_V2, ABENCDS_UNTYPED_LITERAL_V2,
verified 2026-09-16]. A text CASE over status codes becomes CHAR(n) of
the longest literal, and a 0–5 criticality becomes INT1. Cast
explicitly when the OData type matters.
- [2026-09-16] **The `ui5-mcp-server` linter cannot see this repo.** The
server is reached over SSE on `mcp.alexzaw.dev`, and `run_ui5_linter` on
`app/` fails with `ENOENT: realpath '/home/alexz/…/arena-plm/app'`
(live 2026-09-16). Its doc/API tools work; its file-based tools
(linter, manifest validation, project info) do not. For real UI5 code
changes, lint locally (`npx @ui5/linter` inside `app/`) or run the
server where the files are.
- [2026-09-16] **The Fiori mock server does not simulate bound actions.**
Without a per-entity `webapp/localService/mainService/data/<Entity>.js`
exporting `executeAction`, `@sap-ux/fe-mockserver-core` 1.7.15 returns
the action data unchanged
(`node_modules/@sap-ux/fe-mockserver-core/dist/mockdata/fileBasedMockData.js:547-549`,
read locally 2026-09-16). Status transitions can be shown only against
the live RAP service, or with a hand-written mock handler.
- [2026-09-16] **Cast the whole CASE to a data element, never each
branch.** "If a data element is specified for `dtype`, the result …
inherits the semantic properties of the data element. An exception to
this is the use of the `CAST` expression within a case distinction."
Write `cast( case … end as abap_boolean preserving type )`.
`PRESERVING TYPE` requires an exact match of built-in type and length
[source: abap-docs /abap-docs-cloud/ABENCDS_CAST_EXPRESSION_V2, verified
2026-09-16]. To guarantee that length, use typed literals in the branches
(`abap.char'X'`, `abap.char' '` are CHAR(1)): an untyped character
literal's length is only "at least as large as the actual length of the
literal" [source: abap-docs /abap-docs-cloud/ABENCDS_TYPED_LITERAL_V2,
ABENCDS_UNTYPED_LITERAL_V2, verified 2026-09-16]. `ABAP_BOOLEAN` is CHAR 1
[source: abap-docs /abap-docs-standard/ABENDATAOBJECTS_TRUE_VALUE_GUIDL,
verified 2026-09-16]. The same caveat means a CASE over untyped status
literals is not provably CHAR(n) of the longest literal.
- [2026-09-16] **`sap-released-objects` has no `SRVB` object type for
public_cloud**, the same gap as `DDLS` (use `CDS_STOB` for views). Binding
release questions cannot be answered from that server.
- [2026-09-15] **Developer business catalogs: `SAP_A4C_BC_*` is the Public
Cloud / BTP ABAP family; `SAP_A4_BC_*` is on-premise / Private Cloud.** On
`my431353` the developer role carries the A4C catalogs (e.g.
`SAP_A4C_BC_DEV_OBJ_DIS_PC`, `SAP_A4C_BC_DEV_UID_PC` [source: sap-docs
sap-help loio f4881a9b9141430dba1c6a76e7f456dc, verified 2026-09-15]); the
`SAP_A4_BC_DEV_UID_PC` name in the fiori-tools-samples README is the wrong
family for this tenant. Split stated by the tenant owner 2026-09-15; no SAP
Help page in the loadout spells it out — do not "fix" a role toward A4.
- [2026-09-15] **Write probes on the dev tenant: `$TMP` and `ZLOCAL` both
fail, for different reasons.** `$TMP` is a classic package, so creating
there checks the Standard ABAP language version and a cloud-development
role is denied with "not authorized to make changes (S_ABPLNGVS)"; `ZLOCAL`
is a structure package ("cannot contain development objects"). Objects go
in a sub-package of `ZLOCAL` (prototyping, no workbench request for
sub-packages created from release 2508) or of `ZCUSTOM_DEVELOPMENT`
(transport layer YDEV, importable into test/prod); ZLOCAL→ZCUSTOM
reassignment is allowed, the reverse is not; `ZLOCAL` plays the `$TMP` role
in Public Cloud [source: sap-docs sap-help loio
a0d80f14fcb74cb1ac8fb6f3d9ad48cc (2608), verified 2026-09-15]. Refusals
verified live via ADT MCP, 2026-09-15.
- [2026-09-14] `sap-released-objects` has no `DDLS` type for public_cloud;
CDS views are catalogued as `CDS_STOB`. A "not found" for `I_PRODUCT` under
`DDLS` is a type-key artefact, not a release verdict — query with
`object_type=CDS_STOB` (verified 2026-09-14).
- [2026-09-14] **A Fiori Elements app generated on hand-written mock metadata
agrees with itself and hides service-shape mismatches.** ABAP Cloud OData V4
services emit `Schema Namespace="com.sap.gateway.<srvd|srvd_a2x>.<service-binding-name>.v0001"
Alias="SAP__self"` — the name in the namespace is the **service binding
(group)**, which is also the first URL segment; the service definition /
alias is the second segment (`/api_currencyexchangerate/srvd_a2x/sap/currencyexchangerate/0001`
→ `…srvd_a2x.api_currencyexchangerate.v0001`; `/api_product/srvd_a2x/sap/product/0002`
[source: sap-docs sap-help loio 5f45f125dfe84c20beb18f5de1512f5a, verified
2026-09-14]). Shown for released A2X services; for custom UI (`srvd`)
bindings it is strongly indicated, not proven — V-2 confirms. Also, entity types suffixed `_Type`, un-suffixed entity sets,
and vocabulary aliases `SAP__common`/`SAP__capabilities`/`SAP__core`
[source: live tenant my429480 EDMX `~/projects/sap-apps/exchange-rates-cap/srv/external/API_CURRENCYEXCHANGERATE.edmx`
lines 13–31, 55, 57, 95, verified 2026-09-14]. Front-end annotation targets
written against any other namespace silently match nothing at runtime (no
columns, no filters, no actions). Reconcile every `Annotations Target`, the
`edmx:Reference` include namespace, and every `DataFieldForAction.Action`
against the live `$metadata` before the first deploy — never trust the mock.
- [2026-09-04] The predecessor's `config/procurement-type.json`,
`catalog-to-planning-strategy.json`, and `arena-category-to-sap.json` were
loaded but **never read by any code path**, and procurement-type's keys
(`MTS`/`OTS`) and values (`E`) do not match the Arena field (`1`–`9` Item
Type) or SAP values (`X`) the code actually used. Do not port these configs
on trust — re-derive every mapping via POC.
- [2026-09-04] Deployment/exposure target is an OPEN decision (PRD OQ-3). The
old estate fronts apps through a shared `mcl-apps` approuter with shared
XSUAA; a CF route mapped to more than one app round-robins and causes ~50%
intermittent 404s. Whatever is chosen, audit routes after every push.
- [2026-09-04] HANA Cloud compute is the dominant cost lever of the old estate;
an auto-stop systemd timer (`sap-apps/ops/hana-autostop`) guards it. If this
package binds HANA, account for the stop/start cycle in the design.
- [2026-09-04] The predecessor kept its approval queue in a SQLite file inside
the CF droplet — wiped on every restart. Durable persistence is a hard
requirement of the rebuild (PRD ARN-003), not an optimization.
- [2026-09-10] Predecessor BOM and DOCUMENTS syncs are **non-idempotent**
(re-approval creates a second MaterialBOM header / duplicate attachments) —
the rebuild's executors must check existence first (ARN-006).
- [2026-09-10] The predecessor uses **two disagreeing change-master lookup
keys** (`startswith(ChangeNumberDescription,'ECO:')` in the product link vs
`ReasonForChangeText eq 'ARENA <eco>'` everywhere else; the 40-char
truncation can split them). The rebuild uses exactly one key.
- [2026-09-10] Document sync links only Arena files with
`storageMethodName === 'WEB'` (URL links, no bytes) — blob-stored files are
silently skipped, and the DOKAR mapping config existed but was ignored
(`BUS1001006`/`text/url` hardcoded). Decide blob handling explicitly in the
rebuild.
- [2026-09-04] **If `.github/agents/sap-odata-*.agent.md`, a root `AGENTS.md`
about "SAP OData Workspace", or `.vscode/mcp.json` pointing at
`sap-odata-mcp.exe` appear in this repo — delete them.** They are scaffolded
(evidence points to the `harieprasad.sap-odata-mcp` VS Code extension writing
its workspace kit on folder open; observed 2026-09-04 14:40, removed same
day). The referenced MCP binary is a Windows .exe that cannot run on this
host, so those agents fabricate SAP results — the documented failure the
founding kit exists to prevent. The root `AGENTS.md` is the dangerous part:
Claude Code reads it as project instructions. [Update 2026-09-04 15:32] The
suspect extension was uninstalled from all machines (verified: deregistered
and marked obsolete on this host; directory purges on next VS Code reload).
If the bundle STILL reappears after this, the extension hypothesis was wrong
— hunt the real writer instead of re-deleting silently.