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:
@@ -8,7 +8,11 @@ tools: Read, Grep, Glob, Edit, Write, Bash, mcp__abap-docs__*, mcp__sap-docs__*,
|
||||
|
||||
## Role
|
||||
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
|
||||
definitions/implementations, service definitions and bindings, and IAM apps —
|
||||
business catalog + business roles are the only access control (ADR-002,
|
||||
|
||||
@@ -2,6 +2,95 @@
|
||||
|
||||
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
|
||||
|
||||
- What changed: I built a login helper at `tools/adt-reentrance-login/`
|
||||
|
||||
@@ -6,23 +6,50 @@
|
||||
|
||||
## What this is
|
||||
|
||||
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. Standalone successor to the Express
|
||||
Approval-gated sync of Arena PLM items into SAP S/4HANA Public Cloud:
|
||||
materials, BOMs, change masters, documents.
|
||||
|
||||
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**
|
||||
— 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
|
||||
approval domain, a Fiori Elements app in the tenant's Fiori launchpad, IAM
|
||||
app / business catalog / business roles as the only access control, and custom
|
||||
CDS views for discoverability. Side-by-side is reduced to one hardened
|
||||
TypeScript **connectivity worker** (Arena webhook/poll/session/files + initial
|
||||
sync executor) — machine-to-machine only, no UI, no user-facing URLs.
|
||||
The on-stack RAP route of ADR-002 is **withdrawn and superseded**. The starter
|
||||
system's customizing tenant `my429480` (client 100) supports key-user
|
||||
extensibility only — no ABAP, no RAP — so the custom RAP business object ADR-002
|
||||
called for has no home in the tenant I work in.
|
||||
|
||||
The acceptance test: a business user finds the app in the Fiori launchpad and
|
||||
its data in the Custom CDS Views app. Anything that fails that test is not done.
|
||||
The application therefore runs **side-by-side against released OData APIs**,
|
||||
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
|
||||
|
||||
@@ -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` |
|
||||
| Is this SAP object released for ABAP Cloud? Successors? | `sap-released-objects` |
|
||||
| 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` |
|
||||
|
||||
When MCP guidance conflicts with training knowledge, follow MCP.
|
||||
|
||||
Live system checks from this box (verified 2026-09-15): the `sap-api` CLI
|
||||
(`/usr/local/bin/sap-api`) reaches the **development** tenant `my431353` by
|
||||
default (credentials in `~/projects/sap-integrations/_shared/.env`; the
|
||||
productive credential is `.env.prod-my429480.bak`) and Arena — API catalog search,
|
||||
Live system checks from this box: as of 2026-09-29 the `sap-api` CLI
|
||||
(`/usr/local/bin/sap-api`) reaches the starter system's **customizing tenant**
|
||||
`my429480` by default (credentials in
|
||||
`~/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 …`),
|
||||
communication arrangements (`comm`), user/role admin (`users`), and read paths
|
||||
for the released business APIs and Arena items. Read commands are fair game
|
||||
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/`)
|
||||
|
||||
@@ -83,20 +114,27 @@ verified sources: `docs/agent-roster.md`.
|
||||
|
||||
| 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` |
|
||||
| TS connectivity worker: Arena API, Cloud SDK OData writes | `worker-developer` |
|
||||
| Read-only SAP review: clean core, contracts, tombstones | `sap-code-reviewer` |
|
||||
| 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/`
|
||||
(Fastify surface + Arena session core; sync executors are stubs until V-2).
|
||||
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:
|
||||
`npm run start-mock` serves it on port 8082; its service identity is
|
||||
provisional until reconciled with the live RAP UI binding at V-2.
|
||||
Nothing in this package has ever been deployed or reached a business user, and
|
||||
no build resumes until OQ-11 is closed. What exists:
|
||||
|
||||
- `worker/` — the TypeScript connectivity worker (Fastify surface + Arena
|
||||
session core; sync executors are stubs). Built, 137 tests green, never
|
||||
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`
|
||||
(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 |
|
||||
| `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 |
|
||||
| `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/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 |
|
||||
|
||||
+9
-1
@@ -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
|
||||
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
|
||||
sequentially** after the header POST. Parallel item POSTs fail SAP's
|
||||
|
||||
@@ -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
|
||||
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
|
||||
S/4HANA, gated by a human approval workflow. Out of scope: every other package
|
||||
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)
|
||||
│ no UI, no user URLs; technical user
|
||||
reads approved / │ writes staged changes
|
||||
executes sync ▼ ▼ via approval BO service binding
|
||||
┌─ SAP S/4HANA Cloud Public (my429480) ─────────────────────────────────────┐
|
||||
│ Z RAP BO "Arena Change Approval" ← staging + state machine + audit │
|
||||
│ Fiori Elements List Report / Object Page ← in the tenant LAUNCHPAD │
|
||||
│ IAM app → business catalog → business roles ← the only access control │
|
||||
│ Custom CDS views over the BO (join I_Product, …) ← Custom CDS Views app │
|
||||
│ Released OData APIs (Product/BOM/ChangeMaster/Attachment) ← sync targets │
|
||||
│ built, 137 tests green, NOT deployed
|
||||
▼
|
||||
Approval store + state machine + audit
|
||||
(side-by-side — host is the open call, OQ-11)
|
||||
│
|
||||
Fiori Elements List Report / Object Page
|
||||
(`app/` — already built, service-repointable)
|
||||
│ released OData APIs, mc-s4hana
|
||||
┌─ 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
|
||||
`com.minicircuits.arenaplm` (List Report / Object Page, TS) in the structural `app/` subfolder
|
||||
(sibling to `worker/`), running on a **mock** OData V4 service — an interim, generator-iterable
|
||||
stand-in. The real on-stack RAP BO + service binding (ARN-002, V-2) and
|
||||
launchpad deployment (ARN-007) remain gated on developer extensibility (V-1).
|
||||
The predecessor `arena-plm` on CF is verified live (`/api/health` 200) and is
|
||||
the base of record for the domain/field shape until the RAP service exists.
|
||||
**Build state (2026-09-29).** What exists: the Fiori Elements UI
|
||||
`com.minicircuits.arenaplm` in `app/`, built and bound to a mock OData V4
|
||||
service; the connectivity worker in `worker/`, built with 137 tests green and
|
||||
never deployed (no deployment descriptor was ever written); and 19 activated
|
||||
RAP objects on the parked development tenant, with their sources kept in
|
||||
`docs/handover/rap/` as reference. Nothing from this package has ever been
|
||||
deployed to Cloud Foundry or reached a business user.
|
||||
|
||||
## Systems & boundaries
|
||||
|
||||
| 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 |
|
||||
| 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
|
||||
|
||||
- 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
|
||||
|
||||
@@ -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-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-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
|
||||
|
||||
@@ -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) |
|
||||
| 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/) |
|
||||
| V-1…V-3 verification POC | Planned — V-1 (ADT access on my429480) is the user-side gate for everything on-stack |
|
||||
| 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) |
|
||||
| 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 |
|
||||
| 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) | **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) | **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 |
|
||||
| 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
@@ -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
|
||||
`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
|
||||
`-api` host: a business-user call there is blocked by UCON (live 2026-09-16, `KNOWLEDGE.md`).
|
||||
preview is added, the backend recorded for the client 080 track is the **UI host**
|
||||
`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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
|
||||
> **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
|
||||
@@ -37,7 +46,9 @@ on this host. This script is that listener.
|
||||
## Run it
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
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`.)
|
||||
|
||||
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 |
|
||||
|---|---|---|
|
||||
| `--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. |
|
||||
| `--timeout <seconds>` | `300` | Give up and write nothing. |
|
||||
| `--out <path>` | `~/.abap-adt-mcp/ticket.json` | Output file, mode 0600 (directory created 0700). |
|
||||
|
||||
Reference in New Issue
Block a user