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>
This commit is contained in:
2026-09-29 10:33:29 -07:00
co-authored by Claude Opus 5
parent 468729eb4e
commit ffd33f4ec0
10 changed files with 332 additions and 57 deletions
+5 -1
View File
@@ -8,7 +8,11 @@ tools: Read, Grep, Glob, Edit, Write, Bash, mcp__abap-docs__*, mcp__sap-docs__*,
## Role ## Role
Implements on-stack ABAP Cloud artifacts for S/4HANA Public Cloud developer Implements on-stack ABAP Cloud artifacts for S/4HANA Public Cloud developer
extensibility on the development tenant `my431353` (ADT destination `0M7DEJI`; productive tenant `my429480`; API-only: no RFC, no custom IDocs): RAP extensibility on the starter system's development tenant `my431353` (client 080; ADT destination
`0M7DEJI`) — **parked as of 2026-09-29**, objects left in place, so this role is dormant until the
client 080 track resumes; the working target is the starter system's customizing tenant `my429480`
(client 100), which supports key-user extensibility only and no ABAP/RAP. Both tenants are
API-only: no RFC, no custom IDocs. Scope when active: RAP
business objects for the approval domain, CDS entities and views, behavior business objects for the approval domain, CDS entities and views, behavior
definitions/implementations, service definitions and bindings, and IAM apps — definitions/implementations, service definitions and bindings, and IAM apps —
business catalog + business roles are the only access control (ADR-002, business catalog + business roles are the only access control (ADR-002,
+89
View File
@@ -2,6 +2,95 @@
Append-only decision log for this package. Append-only decision log for this package.
## 2026-09-29 — Tooling retargeted to the starter customizing tenant; its credential is rejected
- What changed:
- I pointed the shared CLI at the starter system's customizing tenant. Both
`_shared/.env` and the root `.env` now carry `SAP_API_URL`,
`SAP_API_USER` and `SAP_API_PASSWORD` for
`https://my429480-api.s4hana.cloud.sap`; the eight `CPI_*` and `ARENA_*`
variables are untouched.
- I renamed both parked credential files so neither name asserts something
false: the client-080 credential is now
`_shared/.env.starter-dev-my431353.bak`, and the client-100 credential is
`_shared/.env.starter-cust-my429480.bak` (formerly `.env.prod-my429480.bak`,
a name that wrongly called it productive).
- I corrected the tenant references in `CLAUDE.md`, `KNOWLEDGE.md`,
`app/README.md`, `docs/handover/rap/README.md` and
`.claude/agents/rap-developer.md`: the customizing tenant is the working
target, the development tenant is parked as of 2026-09-29 with its objects
in place. No historical build record was deleted.
- I wrote `docs/adr/ADR-004-back-out-of-on-stack-rap.md` and marked ADR-002
superseded in its own file, including the note that its gate "confirm
developer-extensibility access on my429480" was unanswerable as written.
- Verification: **the customizing-tenant credential is rejected.** Read-only
GETs return HTTP 401 with SAP's logon-failed page (`Anmeldung
fehlgeschlagen`); the host resolves and answers, so this is the credential,
not reachability. I then checked every other way in and found none: the
rejected password is the only copy of that credential anywhere in my estate;
the Cloud Foundry token is expired, so the `mc-s4hana` destination is out of
reach; and the client-certificate path in the shared client looks for
`_shared/certs/az-api-user.crt` and `.key`, which do not exist. No writes of
any kind were issued to any tenant.
- Affected: `_shared/.env`, `.env`, both `.bak` files, five reference documents,
ADR-002, new ADR-004. No SAP tenant was modified.
- Decision: I left the retarget in place rather than rolling back to the
development tenant, because reverting would only restore access to the tenant
I am deliberately leaving. Restoring read access to the customizing tenant is
now a prerequisite for any verification, and the cheapest route is a Cloud
Foundry re-login — that reaches the tenant through the `mc-s4hana` destination
and needs no password at all, which is also what my coding standard requires.
## 2026-09-29 — ADR-004: I withdraw the on-stack RAP route; development tenant parked
- What changed: I corrected a tenant mislabel that had propagated through this
package, and on the corrected facts I withdrew ADR-002.
- Both `my429480` and `my431353` are tenants of the **starter system**.
`my429480` is its **customizing** tenant (client 100); `my431353` is its
**development** tenant (client 080). This package had `my429480` recorded
as "productive" and treated `my431353` as a separate development system;
both readings were wrong, and the parked credential file name
(`.env.prod-my429480.bak`) encoded the same error.
- The customizing tenant supports **key-user extensibility only** — no ABAP,
no RAP; developer extensibility exists only on client 080 [source:
fiori-tools-samples `misc/s4hana/README` "Tenant Types", verified
2026-09-29].
- I therefore parked the development tenant `my431353`, leaving all 19
activated `ZARENA_PLM` objects in place, and moved the application back to
a side-by-side runtime against released APIs.
- I rewrote the PRD accordingly: new target architecture, corrected
Systems & boundaries rows, amended acceptance test, ADR-002 marked
superseded, ADR-004 added, and the RAP-dependent verification items
(V-2, V-3, OQ-5, OQ-8, OQ-9, OQ-10) parked rather than closed (OQ-12).
- Why: I am not carrying an ABAP/RAP build for this package, and the tenant I
am working in cannot host one even if I wanted to. Keeping a PRD that
asserted an impossible architecture would have been worse than the rebuild.
- Affected: PRD.md (vision, target architecture, systems, decisions, open
questions, status), the parked tenant `my431353`, ADR-002.
- Decision: ADR-004. I park rather than delete, so the RAP route stays
reversible at zero cost. I left the replacement host open as OQ-11 —
key-user extensibility in the tenant versus a CAP service side-by-side —
and recorded my recommendation for CAP, because the connectivity worker has
to be side-by-side regardless and one runtime beats two. I will not start
building until OQ-11 is decided.
## 2026-09-29 — Outstanding sources committed and pushed
- What changed: I committed the working-tree state that had sat uncommitted
since the initial `upload current sources` commit, and pushed it: `468729e`,
42 files, 4614 insertions, 1697 deletions, fast-forward onto `origin/main`.
It carries the renamed RAP handover sources (the 11 generator-suffixed
`zz*000` names replaced by the clean object names actually built on the
tenant), the `app/` rebind edits, the build record through 2026-09-19, the
retained reentrance-login helper and the captured live `$metadata`. It drops
two files that never belonged in the repository: a tracked Eclipse installer
under a URL-mangled filename, and a machine-specific workspace file.
- Why: the package held six weeks of unversioned work, and I was about to
change direction. Nothing should be lost across that pivot.
- Affected: the whole repository; `origin/main` now matches the working tree.
- Decision: I committed the deletions as they stood rather than restoring
either file. Neither is source.
## 2026-09-18 — Reentrance-ticket login for `abap-adt-mcp`: built, tested, rejected ## 2026-09-18 — Reentrance-ticket login for `abap-adt-mcp`: built, tested, rejected
- What changed: I built a login helper at `tools/adt-reentrance-login/` - What changed: I built a login helper at `tools/adt-reentrance-login/`
+65 -27
View File
@@ -6,23 +6,50 @@
## What this is ## What this is
Approval-gated sync of Arena PLM items into SAP S/4HANA Public Cloud Approval-gated sync of Arena PLM items into SAP S/4HANA Public Cloud:
(`my429480.s4hana.cloud.sap` productive; development tenant `my431353.s4hana.cloud.sap` since 2026-09-15 — API-only tenants: no RFC, no custom IDocs): materials, BOMs, change masters, documents.
materials, BOMs, change masters, documents. Standalone successor to the Express
Both tenants named in this repo belong to the **same starter system**. The
working target is the starter system's **customizing tenant**
`my429480.s4hana.cloud.sap` (client 100 — key-user extensibility and
configuration only; no ABAP, no RAP). The starter system's **development
tenant** `my431353.s4hana.cloud.sap` (client 080 — developer extensibility) is
**parked as of 2026-09-29**, with the objects I built there left in place. Both
tenants are API-only: no RFC, no custom IDocs.
Standalone successor to the Express
implementation at `~/projects/sap-apps/arena-plm`, which is **reference-only** implementation at `~/projects/sap-apps/arena-plm`, which is **reference-only**
— consult it for behavior, never extend it. — consult it for behavior, never extend it.
## Architecture (ADR-002, 2026-09-04 — on-stack first) ## Architecture (ADR-004, 2026-09-29 — side-by-side against released APIs)
The application lives **in the tenant**: a custom RAP business object for the The on-stack RAP route of ADR-002 is **withdrawn and superseded**. The starter
approval domain, a Fiori Elements app in the tenant's Fiori launchpad, IAM system's customizing tenant `my429480` (client 100) supports key-user
app / business catalog / business roles as the only access control, and custom extensibility only — no ABAP, no RAP — so the custom RAP business object ADR-002
CDS views for discoverability. Side-by-side is reduced to one hardened called for has no home in the tenant I work in.
TypeScript **connectivity worker** (Arena webhook/poll/session/files + initial
sync executor) — machine-to-machine only, no UI, no user-facing URLs.
The acceptance test: a business user finds the app in the Fiori launchpad and The application therefore runs **side-by-side against released OData APIs**,
its data in the Custom CDS Views app. Anything that fails that test is not done. with the customizing tenant as the sync target and configuration home. The
replacement host is deliberately left **open as OQ-11**: key-user extensibility
in the customizing tenant (custom business object plus a low-code UI) versus a
CAP service side-by-side on BTP. My recommendation is **CAP** — the
connectivity worker has to live side-by-side whatever else happens, and one
runtime beats two. **No build starts until OQ-11 is closed.**
Kept, unchanged in value: the hardened TypeScript **connectivity worker**
(Arena webhook/poll/session/files + initial sync executor) — machine-to-machine
only, no UI, no user-facing URLs, and needed under either OQ-11 option — and
the Fiori Elements app in `app/`, which is repointable.
**Parked reference, not deleted:** the RAP approval business object I built on
the starter system's development tenant `my431353` (client 080). All 19
`ZARENA_PLM` objects are left active there and their sources stay in
`docs/handover/rap/`, so that route stays reversible at zero cost.
The acceptance test, as amended by ADR-004: a business user finds the
application from the S/4HANA launchpad and access is governed by business
roles. The "its data in the Custom CDS Views app" clause is withdrawn — it is
unreachable from client 100.
## Operating rules ## Operating rules
@@ -59,20 +86,24 @@ its data in the Custom CDS Views app. Anything that fails that test is not done.
| RAP guides, extensibility docs, SAP Help / Community | `sap-docs` | | RAP guides, extensibility docs, SAP Help / Community | `sap-docs` |
| Is this SAP object released for ABAP Cloud? Successors? | `sap-released-objects` | | Is this SAP object released for ABAP Cloud? Successors? | `sap-released-objects` |
| Fiori Elements, `@UI` annotations, manifest | `fiori-mcp-server` | | Fiori Elements, `@UI` annotations, manifest | `fiori-mcp-server` |
| Writing objects INTO the development tenant (create/activate/transport/ATC/unit tests) | `adt-mcp` — SAP ADT MCP Server from `sapse.adt-vscode`, `http://127.0.0.1:2236/mcp`; bearer token lives in `~/.vscode-server/data/Machine/settings.json` and changes on VS Code reload — refresh `.mcp.json` then | | Writing objects INTO the starter system's development tenant (create/activate/transport/ATC/unit tests) — **parked 2026-09-29 with that tenant** | `adt-mcp` — SAP ADT MCP Server from `sapse.adt-vscode`, `http://127.0.0.1:2236/mcp`; bearer token lives in `~/.vscode-server/data/Machine/settings.json` and changes on VS Code reload — refresh `.mcp.json` then |
| UI5 controls/views (only if custom UI proves necessary) | `ui5-mcp-server` | | UI5 controls/views (only if custom UI proves necessary) | `ui5-mcp-server` |
When MCP guidance conflicts with training knowledge, follow MCP. When MCP guidance conflicts with training knowledge, follow MCP.
Live system checks from this box (verified 2026-09-15): the `sap-api` CLI Live system checks from this box: as of 2026-09-29 the `sap-api` CLI
(`/usr/local/bin/sap-api`) reaches the **development** tenant `my431353` by (`/usr/local/bin/sap-api`) reaches the starter system's **customizing tenant**
default (credentials in `~/projects/sap-integrations/_shared/.env`; the `my429480` by default (credentials in
productive credential is `.env.prod-my429480.bak`) and Arena — API catalog search, `~/projects/sap-integrations/_shared/.env`; the parked development-tenant
credential is `.env.starter-dev-my431353.bak` and the customizing-tenant copy is
`.env.starter-cust-my429480.bak`, both in the same folder) and Arena — API catalog search,
EDMX fetch, OpenAPI generation (`sap-api apis generateOpenapi --service …`), EDMX fetch, OpenAPI generation (`sap-api apis generateOpenapi --service …`),
communication arrangements (`comm`), user/role admin (`users`), and read paths communication arrangements (`comm`), user/role admin (`users`), and read paths
for the released business APIs and Arena items. Read commands are fair game for the released business APIs and Arena items. Read commands are fair game
for design and acceptance; mutating commands are delegated like any other for design and acceptance; mutating commands are delegated like any other
write. write. The retarget is in place, but the `my429480` credential itself answered
HTTP 401 ("Anmeldung fehlgeschlagen") on 2026-09-29 — it needs refreshing before
any CLI call against that tenant succeeds.
## Delegation (project agents in `.claude/agents/`) ## Delegation (project agents in `.claude/agents/`)
@@ -83,20 +114,27 @@ verified sources: `docs/agent-roster.md`.
| Work | Agent | | Work | Agent |
|---|---| |---|---|
| On-stack ABAP Cloud: RAP BO, CDS, behavior, IAM artifacts | `rap-developer` | | On-stack ABAP Cloud: RAP BO, CDS, behavior, IAM artifacts — **dormant** while the RAP route is parked (ADR-004) | `rap-developer` |
| Fiori Elements app, `@UI` annotations, manifest, launchpad | `fiori-developer` | | Fiori Elements app, `@UI` annotations, manifest, launchpad | `fiori-developer` |
| TS connectivity worker: Arena API, Cloud SDK OData writes | `worker-developer` | | TS connectivity worker: Arena API, Cloud SDK OData writes | `worker-developer` |
| Read-only SAP review: clean core, contracts, tombstones | `sap-code-reviewer` | | Read-only SAP review: clean core, contracts, tombstones | `sap-code-reviewer` |
| Tests for worker + service layers | `test-engineer` | | Tests for worker + service layers | `test-engineer` |
## Repo state & commands (verified 2026-09-14) ## Repo state & commands (verified 2026-09-29)
Implementation so far: the TypeScript connectivity worker in `worker/` Nothing in this package has ever been deployed or reached a business user, and
(Fastify surface + Arena session core; sync executors are stubs until V-2). no build resumes until OQ-11 is closed. What exists:
The on-stack RAP track has no code yet — gated on V-1. The Fiori Elements app
(`app/`, TypeScript) is scaffolded against a **mock** OData V4 service: - `worker/` — the TypeScript connectivity worker (Fastify surface + Arena
`npm run start-mock` serves it on port 8082; its service identity is session core; sync executors are stubs). Built, 137 tests green, never
provisional until reconciled with the live RAP UI binding at V-2. deployed. Needed under either OQ-11 option.
- `app/` — the Fiori Elements app (TypeScript), bound to a **mock** OData V4
service: `npm run start-mock` serves it on port 8082. Its service identity is
provisional; it gets repointed once OQ-11 names the host.
- `docs/handover/rap/` — the sources for the 19 `ZARENA_PLM` objects I
activated on the starter system's development tenant `my431353`, parked
2026-09-29 with the objects left in place. Reference and a reversible route,
not a live track.
In `worker/`: `npm run build` (tsc), `npm run lint` (eslint), `npm test` In `worker/`: `npm run build` (tsc), `npm run lint` (eslint), `npm test`
(vitest), `npm run dev` (tsx watch). The worker's HTTP surface is governed by (vitest), `npm run dev` (tsx watch). The worker's HTTP surface is governed by
@@ -109,7 +147,7 @@ In `worker/`: `npm run build` (tsc), `npm run lint` (eslint), `npm test`
| `PRD.md` | Living requirements, target architecture, contracts, verification items | | `PRD.md` | Living requirements, target architecture, contracts, verification items |
| `CHANGELOG.md` | Append-only decision log | | `CHANGELOG.md` | Append-only decision log |
| `KNOWLEDGE.md` | Dated tombstones & landmines — the only knowledge carried from the predecessor; also check it when anything unexpected appears in the repo | | `KNOWLEDGE.md` | Dated tombstones & landmines — the only knowledge carried from the predecessor; also check it when anything unexpected appears in the repo |
| `docs/adr/` | Architecture decision records (ADR-001 amended by ADR-002) | | `docs/adr/` | Architecture decision records (ADR-004 supersedes ADR-002 and partly revives ADR-001) |
| `docs/agent-roster.md` | Specialist-agent design + verified sources | | `docs/agent-roster.md` | Specialist-agent design + verified sources |
| `docs/predecessor-flow.md` | How the Express predecessor actually works (extracted 2026-09-10) — read before designing executor, poller, or approval behavior | | `docs/predecessor-flow.md` | How the Express predecessor actually works (extracted 2026-09-10) — read before designing executor, poller, or approval behavior |
| `.claude/hooks/` | ADR-003 enforcement scripts (grounding injections, consult gate, consult marker); `tests/run.sh` pipe-tests them — run it after any hook change | | `.claude/hooks/` | ADR-003 enforcement scripts (grounding injections, consult gate, consult marker); `tests/run.sh` pipe-tests them — run it after any hook change |
+9 -1
View File
@@ -7,7 +7,15 @@ 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 ground truth. Every entry is dated; re-verify on first POC contact. Add new
entries the same way — dated and falsifiable. entries the same way — dated and falsifiable.
## SAP S/4HANA (tenant `my429480`, Public Cloud, API-only) **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 - [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 sequentially** after the header POST. Parallel item POSTs fail SAP's
+49 -22
View File
@@ -15,39 +15,63 @@ Views app, and access is governed by business roles** — with the side-by-side
footprint reduced to the one thing that cannot run in the tenant: Arena footprint reduced to the one thing that cannot run in the tenant: Arena
connectivity. connectivity.
**Amended 2026-09-29.** I wrote that acceptance test assuming I could build
in the tenant. I cannot, in the tenant I am now working in: the starter
system's customizing tenant `my429480` (client 100) supports key-user
extensibility only, so "its data in the Custom CDS Views app" is not
reachable there and the RAP half of the test is withdrawn (ADR-004). What I
keep is the part that actually mattered: **a business user finds the
application from the S/4HANA launchpad and access is governed by business
roles.**
In scope: material, BOM, change-master, and document sync from Arena to In scope: material, BOM, change-master, and document sync from Arena to
S/4HANA, gated by a human approval workflow. Out of scope: every other package S/4HANA, gated by a human approval workflow. Out of scope: every other package
of the old estate — one package at a time. of the old estate — one package at a time.
## Target architecture (ADR-002, 2026-09-04) ## Target architecture (ADR-004, 2026-09-29 — supersedes ADR-002)
The starter system's **customizing** tenant `my429480` (client 100) supports
**key-user extensibility only** — no ABAP, no RAP. ABAP development requires
the starter system's **development** tenant `my431353` (client 080), which I
parked on 2026-09-29 [source: fiori-tools-samples `misc/s4hana/README`
"Tenant Types", verified 2026-09-29]. The on-stack RAP business object of
ADR-002 therefore has no home in the tenant I am now working in, and the
application moves back out to a side-by-side runtime consuming released APIs.
``` ```
Arena PLM ──webhook + delta poll──▶ Connectivity worker (BTP CF, hardened TS) Arena PLM ──webhook + delta poll──▶ Connectivity worker (BTP CF, hardened TS)
│ no UI, no user URLs; technical user │ built, 137 tests green, NOT deployed
reads approved / │ writes staged changes ▼
executes sync ▼ ▼ via approval BO service binding Approval store + state machine + audit
┌─ SAP S/4HANA Cloud Public (my429480) ─────────────────────────────────────┐ (side-by-side — host is the open call, OQ-11)
│ Z RAP BO "Arena Change Approval" ← staging + state machine + audit │ │
│ Fiori Elements List Report / Object Page ← in the tenant LAUNCHPAD │ Fiori Elements List Report / Object Page
│ IAM app → business catalog → business roles ← the only access control │ (`app/` — already built, service-repointable)
│ Custom CDS views over the BO (join I_Product, …) ← Custom CDS Views app │ │ released OData APIs, mc-s4hana
│ Released OData APIs (Product/BOM/ChangeMaster/Attachment) ← sync targets │ ┌─ Starter system · CUSTOMIZING tenant `my429480` (client 100) ─────────────┐
│ Product / BOM / ChangeMaster / Attachment released APIs ← sync targets │
│ Key-user extensibility + configuration only — no ABAP, no RAP │
│ Launchpad reachability for the app: decided with OQ-11 │
└───────────────────────────────────────────────────────────────────────────┘ └───────────────────────────────────────────────────────────────────────────┘
parked 2026-09-29 ──▶ Starter system · DEVELOPMENT tenant `my431353` (080)
19 RAP objects live in ZARENA_PLM, left in place
``` ```
**Build state (2026-09-14):** the Fiori Elements UI layer is scaffolded as **Build state (2026-09-29).** What exists: the Fiori Elements UI
`com.minicircuits.arenaplm` (List Report / Object Page, TS) in the structural `app/` subfolder `com.minicircuits.arenaplm` in `app/`, built and bound to a mock OData V4
(sibling to `worker/`), running on a **mock** OData V4 service — an interim, generator-iterable service; the connectivity worker in `worker/`, built with 137 tests green and
stand-in. The real on-stack RAP BO + service binding (ARN-002, V-2) and never deployed (no deployment descriptor was ever written); and 19 activated
launchpad deployment (ARN-007) remain gated on developer extensibility (V-1). RAP objects on the parked development tenant, with their sources kept in
The predecessor `arena-plm` on CF is verified live (`/api/health` 200) and is `docs/handover/rap/` as reference. Nothing from this package has ever been
the base of record for the domain/field shape until the RAP service exists. deployed to Cloud Foundry or reached a business user.
## Systems & boundaries ## Systems & boundaries
| System | Role | Boundary | | System | Role | Boundary |
|---|---|---| |---|---|---|
| SAP S/4HANA Cloud Public (`my429480`) | **Application host** (RAP BO, Fiori app, CDS views) and sync target | Developer extensibility (ABAP Cloud via ADT); released APIs only | | Starter system, **customizing** tenant (`my429480`, client 100) | **Sync target** and configuration home | Key-user extensibility only — no ABAP, no RAP; released OData APIs via `mc-s4hana` |
| Starter system, **development** tenant (`my431353`, client 080) | **Parked 2026-09-29** — former RAP application host | Developer extensibility; 19 objects left active in `ZARENA_PLM`, no transport recording |
| Arena PLM (`api.arenasolutions.com/v1`) | Source of items, BOMs, changes, files | REST; webhook + delta poll, handled by the worker | | Arena PLM (`api.arenasolutions.com/v1`) | Source of items, BOMs, changes, files | REST; webhook + delta poll, handled by the worker |
| Connectivity worker (BTP CF) | Arena connectivity + initial sync executor | Machine-to-machine only; technical user via communication arrangement | | Connectivity worker (BTP CF) | Arena connectivity + initial sync executor | Machine-to-machine only; technical user via communication arrangement |
@@ -105,7 +129,8 @@ once V-1 opens the development tenant.
## Architecture decisions ## Architecture decisions
- ADR-001 — toolchain-must-engage rebuild; Express predecessor reference-only. **Amended by ADR-002.** - ADR-001 — toolchain-must-engage rebuild; Express predecessor reference-only. **Amended by ADR-002.**
- ADR-002 — on-stack first: RAP + Fiori Elements in the tenant; side-by-side reduced to a connectivity worker; CAP exits the architecture. - ADR-002 — on-stack first: RAP + Fiori Elements in the tenant; side-by-side reduced to a connectivity worker; CAP exits the architecture. **Superseded by ADR-004.**
- ADR-004 (2026-09-29) — I withdraw the on-stack RAP route and move the application back to a side-by-side runtime against released APIs. Two facts force it: the customizing tenant `my429480` (client 100) supports key-user extensibility only, and I am no longer willing to carry an ABAP/RAP build for this package. I park the development tenant `my431353` (client 080) with its 19 activated objects in place rather than delete them, so the route stays reversible. The replacement host — key-user extensibility in the tenant versus a CAP service side-by-side — is OQ-11; my recommendation is CAP, because the connectivity worker must be side-by-side regardless and one runtime beats two.
## Verification items & open questions ## Verification items & open questions
@@ -121,6 +146,8 @@ once V-1 opens the development tenant.
| OQ-10 | Ownership of UI annotations: the backend metadata extension `ZC_CHANGEAPPROVAL` or the app's local `annotation.xml`. Today 35 of the 58 local annotations override a backend annotation with the same target, term and qualifier (layering rule [source: fiori-mcp-server "Visualizing and Managing Annotations with SAP Fiori Tools - Service Modeler", verified 2026-09-16]), so a DDLX change to those terms is invisible in the app. The local file adds i18n labels, action criticality, the `#Default` variants and the facet IDs the OPA journey relies on | Open (2026-09-16). Interim rule: a term defined locally is changed locally. I consolidate before launchpad deployment | | OQ-10 | Ownership of UI annotations: the backend metadata extension `ZC_CHANGEAPPROVAL` or the app's local `annotation.xml`. Today 35 of the 58 local annotations override a backend annotation with the same target, term and qualifier (layering rule [source: fiori-mcp-server "Visualizing and Managing Annotations with SAP Fiori Tools - Service Modeler", verified 2026-09-16]), so a DDLX change to those terms is invisible in the app. The local file adds i18n labels, action criticality, the `#Default` variants and the facet IDs the OPA journey relies on | Open (2026-09-16). Interim rule: a term defined locally is changed locally. I consolidate before launchpad deployment |
| OQ-8 | Per-operation authorization for the approval BO. Today it is `authorization master ( none )`: any holder of the UI app can approve, reject and retry, and any tenant ABAP code can create and mark* through EML. SAP Help calls `( none )` "not recommended in real-world scenarios". The target is `( global )` with a `FOR GLOBAL AUTHORIZATION` handler and `AUTHORITY-CHECK OBJECT` on a custom authorization object: decisions for business roles, create/mark* for the communication role. First verify that custom authorization objects can be created on `my431353` [source: abap-docs /abap-docs-cloud/ABENBDL_AUTHORIZATION, ABAPHANDLER_METH_GLOBAL_AUTH; sap-docs sap-help loio 673c05562e144702a080c574c3da2da3, verified 2026-09-16 by my review] | Open (2026-09-16): does not block the dev-tenant UI POC; must close before any business role other than the developer's gets the app (IAM brief) | | OQ-8 | Per-operation authorization for the approval BO. Today it is `authorization master ( none )`: any holder of the UI app can approve, reject and retry, and any tenant ABAP code can create and mark* through EML. SAP Help calls `( none )` "not recommended in real-world scenarios". The target is `( global )` with a `FOR GLOBAL AUTHORIZATION` handler and `AUTHORITY-CHECK OBJECT` on a custom authorization object: decisions for business roles, create/mark* for the communication role. First verify that custom authorization objects can be created on `my431353` [source: abap-docs /abap-docs-cloud/ABENBDL_AUTHORIZATION, ABAPHANDLER_METH_GLOBAL_AUTH; sap-docs sap-help loio 673c05562e144702a080c574c3da2da3, verified 2026-09-16 by my review] | Open (2026-09-16): does not block the dev-tenant UI POC; must close before any business role other than the developer's gets the app (IAM brief) |
| OQ-7 | Tenant object naming and cleanup for the approval BO | **Closed 2026-09-16.** The package was deleted in ADT, contents and package itself (verified live through ADT MCP validation, 2026-09-16). I build from scratch, without the generator: table `ZCHANGEAPPROVAL`, `ZR_CHANGEAPPROVAL`, `ZBP_R_CHANGEAPPROVAL`, `ZC_CHANGEAPPROVAL`, SRVD `ZUI_ARENA_CHANGE_APPROVAL` with SRVB `ZUI_ARENA_CHANGE_APPR_O4`, and SRVD `ZAPI_ARENA_CHANGE_APPROVAL` with SRVB `ZAPI_ARENA_CHANGE_APPR_A2X`. Binding names follow SAP's 26-character limit (RAP-5). Entity set is `ChangeApproval`; the A2X projection and parameter entity names are unchanged | | OQ-7 | Tenant object naming and cleanup for the approval BO | **Closed 2026-09-16.** The package was deleted in ADT, contents and package itself (verified live through ADT MCP validation, 2026-09-16). I build from scratch, without the generator: table `ZCHANGEAPPROVAL`, `ZR_CHANGEAPPROVAL`, `ZBP_R_CHANGEAPPROVAL`, `ZC_CHANGEAPPROVAL`, SRVD `ZUI_ARENA_CHANGE_APPROVAL` with SRVB `ZUI_ARENA_CHANGE_APPR_O4`, and SRVD `ZAPI_ARENA_CHANGE_APPROVAL` with SRVB `ZAPI_ARENA_CHANGE_APPR_A2X`. Binding names follow SAP's 26-character limit (RAP-5). Entity set is `ChangeApproval`; the A2X projection and parameter entity names are unchanged |
| OQ-11 | Where the approval store, state machine and audit live now that ADR-004 withdrew the RAP BO. Option A: key-user extensibility in the customizing tenant (custom business object + low-code UI) — stays in the tenant and in the launchpad natively, but the Arena connectivity still needs an outside worker, so the application ends up with two homes, and key-user objects are transport-bound. Option B: a CAP service side-by-side on BTP CF — one runtime with the worker, matches the archetype the rest of my estate already runs, and `app/` repoints to it cheaply because 35 of its 58 annotations are already local (OQ-10); the cost is BTP runtime and launchpad reachability becomes a federation question. | Open (2026-09-29). I recommend Option B. Decide before any further build. |
| OQ-12 | The ABAP/RAP-dependent items V-2, V-3, OQ-5, OQ-8, OQ-9 and OQ-10 are all scoped to the parked development tenant. They are **parked with ADR-004**, not closed; each returns only if the RAP route is revived. | Parked (2026-09-29) |
## Status ## Status
@@ -130,8 +157,8 @@ once V-1 opens the development tenant.
| Developer environment | Done (2026-09-04); MCP loadout revised to ABAP/RAP set (done 2026-09-04) | | Developer environment | Done (2026-09-04); MCP loadout revised to ABAP/RAP set (done 2026-09-04) |
| Ground-truth enforcement kit (ADR-003 hooks) | Done (2026-09-04); hardened 2026-09-14 — Bash/MultiEdit/filesystem writes gated, grounding-only marker refresh, portable paths, fail-closed, 37 pipe-tests green | | Ground-truth enforcement kit (ADR-003 hooks) | Done (2026-09-04); hardened 2026-09-14 — Bash/MultiEdit/filesystem writes gated, grounding-only marker refresh, portable paths, fail-closed, 37 pipe-tests green |
| Specialist agent roster (5 agents, docs/agent-roster.md) | Done (2026-09-04; all 5 files YAML-verified in .claude/agents/) | | Specialist agent roster (5 agents, docs/agent-roster.md) | Done (2026-09-04; all 5 files YAML-verified in .claude/agents/) |
| V-1…V-3 verification POC | Planned — V-1 (ADT access on my429480) is the user-side gate for everything on-stack | | V-1…V-3 verification POC | V-1 **Closed 2026-09-15** on the development tenant. V-2/V-3 **parked 2026-09-29** with ADR-004. The old note that V-1 meant "ADT access on my429480" was wrong: `my429480` is the customizing tenant and grants no developer extensibility at all |
| Fiori Elements app (`app/`, mock-bound) | Done for the mock stage (2026-09-14) — gateway service shape (binding-derived identity), six-state domain, polished List Report/Object Page, launchpad inbound `ArenaChangeApproval-manage`; SAP review findings closed. Deploy gated on V-1/V-2 (live `$metadata` reconciliation) | | Fiori Elements app (`app/`, mock-bound) | Done for the mock stage (2026-09-14) — gateway service shape (binding-derived identity), six-state domain, polished List Report/Object Page, launchpad inbound `ArenaChangeApproval-manage`; SAP review findings closed. Deploy gated on V-1/V-2 (live `$metadata` reconciliation) | **2026-09-29: still mock-bound and never deployed.** Its target service is now OQ-11, not the RAP UI binding |
| RAP BO (approval domain) | In progress (2026-09-16): from-scratch build in package `ZARENA_PLM` (under `ZLOCAL`, no transport recording) under the clean names (OQ-7 closed). The handover in `docs/handover/rap/` has all pre-paste review fixes applied and was stable as of 02:45. Wave A (U1–U5: table, three parameter entities, root view) was created empty at 02:30. Its sources were pasted at 02:47, and all five activated at 02:49 with no errors, `preserving type` included. Wave B (U6 base BDEF, U10 root access control) was created empty at 02:50, its sources were pasted at 02:53, and both activated at 02:55 (BDEF through `.bdef.abdl`). Wave C (U7 behavior pool, U8 UI projection view) was pasted at ~03:00 and activated at 03:03 (U6 and U7 together, then U8), with no errors. It is not yet confirmed that the handler source sits in the class's Local Types include; until it is, activation does not prove the three flagged constructs. Wave D (U9 projection BDEF, U11 access control, U12 metadata extension, U13 UI service definition) was created empty at 03:05 and pasted at ~04:12. U9, U11 and U12 activated at 04:15. U13 activation failed, listing "Comments are not supported and will be deleted on save" (Ln 1) and "oData V4 services with no draft capability will be primarily READ-ONLY" (Ln 21, expected by design). After a comment-free re-save, U13 activated at 04:18. U14 binding `ZUI_ARENA_CHANGE_APPR_O4` (OData V4 UI) was created and activated. **The UI leg is active: all 14 objects; ATC 0 errors, 0 warnings, 43 infos.** **Published 2026-09-16 04:26** through the ADT Publish code lens: `https://my431353-api.s4hana.cloud.sap/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/?sap-client=080`, entity set `ChangeApproval` (`fetch_service_information`). The table is empty until the worker leg creates records, because the UI exposes no create. V-2 app reconciliation done. **Worker (A2X) leg ACTIVE 2026-09-16 06:37:** W1 view `ZC_CHANGEAPPROVAL_A2X`, W2 access control, W3 projection BDEF (create, markExecuting, markSynced, markFailed), W4 service definition `ZAPI_ARENA_CHANGE_APPROVAL` and W5 OData V4 Web API binding `ZAPI_ARENA_CHANGE_APPR_A2X` (unpublished, service `0001`). ATC on the 5 worker objects: 0 errors, 1 priority-3 warning (W607 on `ZC_CHANGEAPPROVAL_A2X`: `authorizationCheck: #CHECK` should be `#MANDATORY`), deferred to OQ-8. **The approval BO is complete on the development tenant (19 objects).** Next: expose W5 to the worker's communication user through a custom communication scenario (V-2 A2X half); IAM app, business catalog and role for the UI app (ARN-007); OQ-8 authorization before other business users. The table source goes into `.tabl.ddic`; `.tabl.json` holds only header metadata. (3) UI leg, 14 sources ending with binding `ZUI_ARENA_CHANGE_APPR_O4`: I create each object through the MCP, its source is pasted in the VS Code editor, and I activate it. The `markSynced`/`markFailed` parameter entities belong to this leg, because the base BDEF references them. (4) Publish the UI binding, then run V-2 reconciliation of the app against its live `$metadata`. (5) Worker (A2X) leg, 4 sources. Syntax proven only by tenant activation, still open: `OPTIONS PRIVILEGED ACCESS` in `checkDuplicate` (fallback `FROM … WITH PRIVILEGED ACCESS`), `%op-%action` on MODIFY response rows, `preserving type` on the U5 boolean casts | | RAP BO (approval domain) | **Parked 2026-09-29 (ADR-004).** Complete and active on the development tenant `my431353`: 19 objects in `ZARENA_PLM`, ATC 0 errors, UI service published 2026-09-16 04:26, A2X binding unpublished. I leave every object in place and keep the sources in `docs/handover/rap/`. Never reached a business user: no IAM app, no business catalog, no business role (ARN-007 never started), and `authorization master ( none )` throughout |
| Connectivity worker | Review wave Done (2026-09-14) — TTL wiring, cursor-after-success, buffer-full = tick failure, health conformance, strict JSON-only validation, bounded buffer, graceful drain, HTTP timeout, fixed-phrase errors; 137 tests green incl. the schema-driven contract-conformance suite. Next: Arena client POC (live), executor leg gated on V-2. **Do not deploy the scaffold**: the ingest buffer has no consumer yet, so a long-running instance would answer 503 after `WEBHOOK_QUEUE_MAX_SIZE` events. Next: Arena client POC (live), executor leg gated on V-2 | | Connectivity worker | Review wave Done (2026-09-14) — TTL wiring, cursor-after-success, buffer-full = tick failure, health conformance, strict JSON-only validation, bounded buffer, graceful drain, HTTP timeout, fixed-phrase errors; 137 tests green incl. the schema-driven contract-conformance suite. Next: Arena client POC (live), executor leg gated on V-2. **Do not deploy the scaffold**: the ingest buffer has no consumer yet, so a long-running instance would answer 503 after `WEBHOOK_QUEUE_MAX_SIZE` events. Next: Arena client POC (live), executor leg gated on V-2 |
| Worker API contract (`docs/api/worker.openapi.json`) | v0.2.1 Done (2026-09-14) — health enums/`degraded`/`poller`, strict `SyncRunRequest`, webhook 503, 413/415 + `default` on every operation, reserved 502, `DOCUMENTS` token; `x-sap-stateInfo: beta`, provisional webhook schema pending Arena POC | | Worker API contract (`docs/api/worker.openapi.json`) | v0.2.1 Done (2026-09-14) — health enums/`degraded`/`poller`, strict `SyncRunRequest`, webhook 503, 413/415 + `default` on every operation, reserved 502, `DOCUMENTS` token; `x-sap-stateInfo: beta`, provisional webhook schema pending Arena POC |
+5 -2
View File
@@ -53,8 +53,11 @@ Tools - Service Modeler", verified 2026-09-16].
**Backend for a non-mock run: not configured.** `ui5.yaml` and `ui5-local.yaml` carry **Backend for a non-mock run: not configured.** `ui5.yaml` and `ui5-local.yaml` carry
`fiori-tools-proxy` with `backend: []`, and `npm start` is a generator placeholder. When a live `fiori-tools-proxy` with `backend: []`, and `npm start` is a generator placeholder. When a live
preview is added, the backend is the **UI host** `https://my431353.s4hana.cloud.sap`, never the preview is added, the backend recorded for the client 080 track is the **UI host**
`-api` host: a business-user call there is blocked by UCON (live 2026-09-16, `KNOWLEDGE.md`). `https://my431353.s4hana.cloud.sap`, never the `-api` host: a business-user call there is blocked
by UCON (live 2026-09-16, `KNOWLEDGE.md`). That tenant — the starter system's development tenant —
is **parked as of 2026-09-29**, so this binding is a reference point, not a live target; the
working target is the starter system's customizing tenant `my429480` (client 100).
## Status model and actions ## Status model and actions
+8 -1
View File
@@ -1,6 +1,13 @@
# ADR-002 — On-stack first: RAP approval domain + Fiori app in the tenant; side-by-side reduced to a connectivity worker # ADR-002 — On-stack first: RAP approval domain + Fiori app in the tenant; side-by-side reduced to a connectivity worker
Date: 2026-09-04 · Status: Accepted (amends ADR-001) Date: 2026-09-04 · Status: **Superseded by ADR-004 (2026-09-29)** (amended ADR-001)
> **Superseded 2026-09-29.** The customizing tenant `my429480` (client 100)
> supports key-user extensibility only, so the RAP business object below has
> no home there; `my429480` and `my431353` are the starter system's
> customizing and development tenants, not a development and a productive
> system. V-1 below, "confirm developer-extensibility access on my429480",
> was unanswerable as written. See ADR-004.
## Context ## Context
@@ -0,0 +1,80 @@
# ADR-004 — Back out of on-stack RAP: side-by-side against released APIs
Date: 2026-09-29 · Status: Accepted (supersedes ADR-002; partly revives ADR-001)
## Context
ADR-002 moved this package on-stack: a RAP approval business object and a Fiori
Elements app inside the tenant, with side-by-side reduced to a connectivity
worker, and CAP written out of the architecture. I built that. On the starter
system's development tenant `my431353` (client 080) the approval business
object is complete and active — 19 objects in `ZARENA_PLM`, ATC clean, the UI
service published on 2026-09-16 — and the Fiori Elements app in `app/` is built
against a mock of it.
Two facts have since changed the ground under that decision.
**The tenant I work in cannot host it.** `my429480` and `my431353` are two
tenants of the same starter system: `my429480` is its **customizing** tenant
(client 100) and `my431353` is its **development** tenant (client 080). The
customizing tenant supports **key-user extensibility only** — no ABAP, no RAP;
developer extensibility exists only on client 080 [source: fiori-tools-samples
`misc/s4hana/README`, "Tenant Types", verified 2026-09-29]. ADR-002 was written
believing `my429480` offered developer extensibility, and this package
compounded the error by recording `my429480` as "productive". Both readings
were wrong.
**I am not carrying the ABAP build.** The RAP route costs more than this
package can justify: every source has to be pasted into an editor by hand,
because no agent-side ABAP authoring path exists (V-4, answered 2026-09-15: no;
SAP's editing tool is planned for Public Edition 2702), and the one workaround
I tried — reentrance-ticket login for a community ADT server — was built,
tested and rejected on evidence (2026-09-18). Outside advice is that no ABAP is
needed for this integration. Nothing I built on-stack ever reached a business
user: ARN-007 (IAM app, business catalog, business role) was never started, and
the business object still runs `authorization master ( none )`.
## Decision
I withdraw the on-stack RAP route. The application moves back out to a
side-by-side runtime consuming released OData APIs, with the customizing tenant
`my429480` (client 100) as the sync target and configuration home.
I **park** the development tenant `my431353` rather than clean it: all 19
objects stay active in `ZARENA_PLM`, and their sources stay in
`docs/handover/rap/`. Parking costs nothing — the package carries no transport
recording and the tenant is non-productive — and it keeps the route reversible
if the constraint or the advice changes.
I do **not** decide the replacement host here. That is OQ-11: key-user
extensibility in the customizing tenant (custom business object plus a low-code
UI) versus a CAP service side-by-side on BTP. My recommendation is CAP, because
the connectivity worker has to live side-by-side whatever else happens, and one
runtime beats two. No build starts until OQ-11 is closed.
## Consequences
Kept, unchanged in value:
- the connectivity worker (`worker/`) — built, 137 tests green, never deployed;
it is the only encoding of the Arena session, delta-cursor and webhook logic
outside the Express predecessor, and it is needed under either OQ-11 option;
- the Fiori Elements app (`app/`) — repointable, because 35 of its 58
annotations are already local rather than backend-owned (OQ-10);
- the RAP sources and the live objects, as reference and as a reversible route.
Withdrawn or weakened:
- the acceptance test's "finds its data in the Custom CDS Views app" clause —
unreachable from client 100; what survives is launchpad reachability and
governance by business roles, and launchpad reachability now becomes a
federation question rather than a native one;
- ADR-002's claim that "CAP exits the architecture" — ADR-001's CAP-first
direction is, in effect, back on the table.
Parked with this decision, not closed: V-2, V-3, OQ-5, OQ-8, OQ-9, OQ-10 — all
scoped to the parked development tenant. Each returns only with the RAP route.
Unrelated to the decision but blocking any verification against the customizing
tenant: the only `AZ_API_USER` credential for `my429480` in my estate is
rejected (HTTP 401), the Cloud Foundry token is expired, and the client
certificate path has no certificates. One of those has to be restored before I
can read that tenant at all.
+6 -1
View File
@@ -1,6 +1,11 @@
# RAP handover: Arena change-approval BO, built from an empty package (rev. 2026-09-16, corrected after the UI leg went live) # RAP handover: Arena change-approval BO, built from an empty package (rev. 2026-09-16, corrected after the UI leg went live)
Target: development tenant `my431353` (ADT destination `0M7DEJI`), package `ZARENA_PLM`, a **Parked 2026-09-29.** This handover records the client 080 build as it was carried out. The
starter system's development tenant `my431353` is parked as of 2026-09-29 and its objects are left
in place; the working target is now the starter system's customizing tenant `my429480` (client 100,
key-user extensibility only — no ABAP/RAP). Keep this document as the build record and reference.
Target: the starter system's development tenant `my431353` (ADT destination `0M7DEJI`), package `ZARENA_PLM`, a
sub-package of `ZLOCAL` with no transport. No generator is used. Every object is created empty sub-package of `ZLOCAL` with no transport. No generator is used. Every object is created empty
through the ADT MCP `abap_creation-create_object`, filled by pasting a file from this folder into through the ADT MCP `abap_creation-create_object`, filled by pasting a file from this folder into
the VS Code ADT editor, saved, and activated through `abap_activate_objects`. The ADT MCP cannot the VS Code ADT editor, saved, and activated through `abap_activate_objects`. The ADT MCP cannot
+16 -2
View File
@@ -6,6 +6,15 @@ headless / SSH-only host — without a browser window on the server's desktop.
Node 24, standard library only, no dependencies, no install step. Node 24, standard library only, no dependencies, no install step.
> **Parked 2026-09-29.** `my431353` is the starter system's **development**
> tenant (client 080). I parked that tenant on 2026-09-29 together with the
> on-stack RAP route, leaving all of its objects active in place. I keep this
> helper only in case that route is revived — nothing in the current
> side-by-side architecture calls it. Every `my431353` reference below is the
> default this tool was built against, not a live target. The working target
> is the starter system's customizing tenant `my429480` (client 100), which
> supports key-user extensibility only and needs no ADT logon at all.
--- ---
## Why this exists ## Why this exists
@@ -37,7 +46,9 @@ on this host. This script is that listener.
## Run it ## Run it
Three steps, three terminals-worth of context. Values below use the defaults Three steps, three terminals-worth of context. Values below use the defaults
(tenant `my431353`, port `42010`, 300 s timeout). (tenant `my431353`, port `42010`, 300 s timeout) — that tenant being the
development tenant parked on 2026-09-29, kept here as the default this tool
shipped with.
### 1. Start the helper on this host ### 1. Start the helper on this host
@@ -69,6 +80,9 @@ redirects your browser to its own machine and nothing is captured.
https://my431353.s4hana.cloud.sap/sap/bc/adt/core/http/reentranceticket?redirect-url=http://localhost:42010/adt/redirect https://my431353.s4hana.cloud.sap/sap/bc/adt/core/http/reentranceticket?redirect-url=http://localhost:42010/adt/redirect
``` ```
That host is the parked development tenant (client 080, parked 2026-09-29);
point `--tenant` elsewhere if the revived route ever lands on another tenant.
(Or capture it programmatically: `node login.mjs --print-url-only`.) (Or capture it programmatically: `node login.mjs --print-url-only`.)
After SSO the tab lands on "Ticket captured", the helper writes After SSO the tab lands on "Ticket captured", the helper writes
@@ -88,7 +102,7 @@ fresh ticket, call the MCP `login` tool for the destination.
| Flag | Default | Meaning | | Flag | Default | Meaning |
|---|---|---| |---|---|---|
| `--tenant <url>` | `https://my431353.s4hana.cloud.sap` | Tenant base URL. The UI host, not the `-api` host. | | `--tenant <url>` | `https://my431353.s4hana.cloud.sap` | Tenant base URL. The UI host, not the `-api` host. The default is the development tenant parked on 2026-09-29. |
| `--port <n>` | `42010` | Loopback port. Bound to `127.0.0.1` **only**; there is no flag to change the bind address. | | `--port <n>` | `42010` | Loopback port. Bound to `127.0.0.1` **only**; there is no flag to change the bind address. |
| `--timeout <seconds>` | `300` | Give up and write nothing. | | `--timeout <seconds>` | `300` | Give up and write nothing. |
| `--out <path>` | `~/.abap-adt-mcp/ticket.json` | Output file, mode 0600 (directory created 0700). | | `--out <path>` | `~/.abap-adt-mcp/ticket.json` | Output file, mode 0600 (directory created 0700). |