Both options framed for OQ-11 failed the deciding criterion: whether the next person finds the thing inside the platform. A CAP service or a hardened worker on Cloud Foundry is discoverable only to whoever already knows the route to it, which is ADR-002's original objection relocated rather than answered. The integration is now Integration Suite native. Nothing on Cloud Foundry, nothing in ABAP: - Arena connectivity as a custom adapter built with the Adapter SDK — sender adapter with the webhook endpoint and delta scheduler, cluster lock for single-flight login, ADK persistency for the delta cursor, tenant user credentials for Arena secrets. - Movement as iFlows to the released Product / BOM / ChangeMaster / Attachment OData APIs. - Human approval in SAP Build Process Automation (entitled in the global account, not yet assigned). Decisive: every mechanism hand-rolled in worker/ has a first-class ADK facility, so the adapter deletes that custom infrastructure rather than merely relocating it; and the ADK's Java/Maven/OSGi toolchain is not a new cost here, because the AS/400 FetchAPI servlets are already Java and Java developers can be staffed in-house. worker/ is reclassified from deliverable to specification: its 137 tests describe the Arena session, delta-cursor and webhook behaviour the adapter must reproduce. app/ has no target service under ADR-005 and is kept as reference, unrepointed. ADR-004's "side-by-side runtime" is narrowed to mean "in Integration Suite". New verification items V-5 (can an ADK adapter hold an Arena session under cluster lock — the first build) and V-6 (where SBPA tasks surface for a business user). No SAP tenant or BTP artifact was modified. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
169 lines
27 KiB
Markdown
169 lines
27 KiB
Markdown
# PRD — arena-plm (standalone rebuild)
|
|
|
|
## Vision & scope
|
|
|
|
I am rebuilding the Arena PLM → SAP S/4HANA integration as a **proper SAP
|
|
application that lives in the tenant**. The predecessor (Express.js,
|
|
`~/projects/sap-apps/arena-plm`) works as a demo but fails the test that
|
|
matters: a business user inside S/4HANA cannot find it — not in the Fiori
|
|
launchpad, not in the Custom CDS Views app — because everything was built
|
|
side-by-side behind standalone URLs with ad-hoc access control.
|
|
|
|
The acceptance test I hold this rebuild to: **a business user finds the
|
|
application in the S/4HANA Fiori launchpad, finds its data in the Custom CDS
|
|
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-005, 2026-09-29 — closes OQ-11; narrows ADR-004)
|
|
|
|
Integration Suite native. Nothing on Cloud Foundry, nothing in ABAP. The
|
|
customizing tenant `my429480` (client 100) supports key-user extensibility only
|
|
— no ABAP, no RAP — so the on-stack RAP business object of ADR-002 has no home
|
|
there [source: fiori-tools-samples `misc/s4hana/README`, "Tenant Types",
|
|
verified 2026-09-29]; and a custom application on Cloud Foundry fails the test
|
|
that matters, which is whether the next person finds it inside the platform.
|
|
|
|
```
|
|
┌─ SAP Integration Suite · Cloud Integration ───────────────────────────────┐
|
|
│ Arena custom adapter (Adapter SDK, Java/OSGi) │
|
|
│ · sender: webhook endpoint + delta scheduler │
|
|
│ · cluster lock -> single-flight Arena login │
|
|
│ · ADK persistency -> delta cursor │
|
|
│ · user credentials -> Arena secrets from the tenant store │
|
|
│ iFlows -> movement: material, BOM, change master, documents │
|
|
└──────────────┬──────────────────────────────────┬─────────────────────────┘
|
|
│ released OData APIs │ approval request
|
|
▼ ▼
|
|
┌─ Starter system · CUSTOMIZING tenant `my429480` ─┐ ┌─ SAP Build Process ──┐
|
|
│ Product / BOM / ChangeMaster / Attachment APIs │ │ Automation │
|
|
│ Key-user extensibility + configuration only │ │ human approval task │
|
|
└──────────────────────────────────────────────────┘ │ (entitled, unassigned)│
|
|
└──────────────────────┘
|
|
|
|
parked ──▶ Starter system · DEVELOPMENT tenant `my431353` (client 080)
|
|
19 RAP objects live in ZARENA_PLM, left in place
|
|
spec ──▶ worker/ — 137 tests describe the Arena behaviour to reproduce
|
|
ref ──▶ app/ — no target service under ADR-005; kept, not repointed
|
|
```
|
|
|
|
**Build state (2026-09-29).** Nothing from this package has ever been deployed
|
|
to Cloud Foundry or reached a business user. What exists: the connectivity
|
|
worker (built, 137 tests green, never deployed, now the specification for the
|
|
adapter); the Fiori Elements app in `app/` (built, mock-bound, no longer the
|
|
UI route); and 19 activated RAP objects on the parked development tenant, with
|
|
sources kept in `docs/handover/rap/`.
|
|
|
|
## Systems & boundaries
|
|
|
|
| System | Role | Boundary |
|
|
|---|---|---|
|
|
| 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 |
|
|
|
|
## Interface contracts
|
|
|
|
Carried from the predecessor, in live use (2026-09-04); re-verify on first POC
|
|
touch. The worker keeps calling these on approval, so every KNOWLEDGE.md
|
|
tombstone remains valid.
|
|
|
|
| API | OData | Path | Notes |
|
|
|---|---|---|---|
|
|
| Product | V4 | `/sap/opu/odata4/sap/api_product/srvd_a2x/sap/product/0002` | deep insert for plant extensions |
|
|
| Product (plant fix) | V2 | `/sap/opu/odata/sap/API_PRODUCT_SRV` | `AvailabilityCheckType` is V2-only |
|
|
| BOM (write) | V2 | `/sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV;v=0002` | header first, then sequential items |
|
|
| BOM (read) | V2 | `/sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV` | v1 only; v2 rejects guid keys |
|
|
| Change Master | V2 | `/sap/opu/odata/sap/API_CHANGEMASTER;v=0002` | object-type assignments, material linking |
|
|
| Attachment | V2 | `/sap/opu/odata/sap/API_CV_ATTACHMENT_SRV` | function import for URL creation |
|
|
| Approval BO — UI binding (Fiori app) | V4 UI | `/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/` (binding `ZUI_ARENA_CHANGE_APPR_O4` on definition `ZUI_ARENA_CHANGE_APPROVAL`; designed 2026-09-16, not yet created) | entity set `ChangeApproval` / type `ChangeApproval_Type`, actions `approve`, `reject(RejectReason)`, `retrySync`; namespace, EDM types and the URL's service alias segment are confirmed from live `$metadata` after publish (V-2). The Fiori app still points at `zui_arena_change_approval_o4`, and V-2 reconciliation moves it |
|
|
| Approval BO — Web API (A2X) binding (worker) | V4 Web API | binding `ZAPI_ARENA_CHANGE_APPR_A2X` on definition `ZAPI_ARENA_CHANGE_APPROVAL` (designed 2026-09-16; created after the A2X projection is active) | custom communication scenario, technical user; namespace from live `$metadata`; exposes create + read + `markExecuting` / `markSynced(SapChangeNumber)` / `markFailed(ErrorMessage)` (RAP-6) |
|
|
| Worker inbound surface | REST (OpenAPI 3.1) | `docs/api/worker.openapi.json` | webhook intake (503 when buffer full), health (`ok`/`degraded`, session `none/active/expired/refreshing`), sync-run admin (strict request schema); contract v0.2.0 (2026-09-14 wave); auth scheme pending OQ-6 (ARN-009) |
|
|
|
|
## Requirements
|
|
|
|
Capability level — field mappings deferred to the POC per my POC-before-spec rule.
|
|
|
|
| ID | Requirement | Status |
|
|
|---|---|---|
|
|
| ARN-001 | Sync chain PRODUCT → CHANGE_MASTER → BOM → DOCUMENTS in config-driven order, executed by the worker on approval | Planned |
|
|
| ARN-002 | Approval domain as an on-stack RAP BO: staging fields, state machine PENDING → APPROVED → EXECUTING → SYNCED \| FAILED, REJECTED terminal, FAILED → retrySync → APPROVED (amended 2026-09-14: a terminal success state is required so an approved record is never executed twice; amended 2026-09-16: retry returns the record to APPROVED so the worker re-claims it through `markExecuting`, the only way into EXECUTING. A retry that jumped straight to EXECUTING was never picked up, or it risked a second concurrent execution); duplicate staging of the same `ItemNumber`+`ChangeType`+`ArenaEcoId` is refused on create while a non-REJECTED record exists (2026-09-16); approve/reject/retrySync as RAP actions with instance feature control; audit fields (`RequestedBy`/`RequestedOn`/`DecidedBy`/`DecidedOn`); execution failure is a distinct state, never overloaded onto rejection (predecessor defect, `docs/predecessor-flow.md` §2) | Planned |
|
|
| ARN-003 | Durable persistence & audit — satisfied structurally by in-tenant RAP persistence (the predecessor lost its queue on every restart) | Planned (by design) |
|
|
| ARN-004 | Business mappings maintained in-tenant — evaluate Business Configuration maintenance objects (Custom Business Configurations app) before any file-based config | Planned |
|
|
| ARN-005 | Arena ingestion via webhook + delta poll in the connectivity worker | Planned |
|
|
| ARN-006 | Idempotent SAP writes, SAP-as-ledger (see `KNOWLEDGE.md`) — predecessor BOM/document syncs were non-idempotent; executors must check existence first | Planned |
|
|
| ARN-007 | Access exclusively via the Fiori launchpad with IAM app / business catalog / business roles; no user-facing standalone URLs | Planned |
|
|
| ARN-008 | Approval data discoverable via custom CDS views, joinable to released views (the discoverability test); look up join targets with `object_type=CDS_STOB` in `sap-released-objects` (no `DDLS` type in the public_cloud dataset, KNOWLEDGE 2026-09-14) | Planned |
|
|
| ARN-009 | API-first: every interface this package owns carries an OpenAPI 3.1 JSON contract under `docs/api/`, authored before or with the change; implementation conforms to the contract | Adopted (2026-09-10) |
|
|
| ARN-010 | The approved payload is the executed payload: the executor writes the staged data the approver saw — never re-fetch-and-recompute at execution time (the predecessor discarded the preview, making approval decorative; `docs/predecessor-flow.md` §2) | Adopted (2026-09-10) |
|
|
|
|
### RAP-track requirements harvested from the UI (2026-09-14)
|
|
|
|
Derived while binding the Fiori app; each becomes a `rap-developer` brief
|
|
once V-1 opens the development tenant.
|
|
|
|
| ID | Requirement | Source |
|
|
|---|---|---|
|
|
| RAP-1 | Behavior definition declares `approve`, `reject`, `retrySync` with `( features : instance )` and implements `get_instance_features` so the UI service emits `Core.OperationAvailable`; approve/reject only for PENDING, retrySync only for FAILED. `approve` writes no `SapChangeNumber` (execution does). The CDS emits numeric `StatusCriticality` 2/2/5/3/1/1 for PENDING/APPROVED/EXECUTING/SYNCED/REJECTED/FAILED (5 = Information is V4-only) | [source: abap-docs /abap-docs-standard/ABENBDL_ACTIONS_FC; sap-docs /abap-fiori-showcase/01_general_features#operations-and-actions, verified 2026-09-14] |
|
|
| RAP-2 | `reject` takes a mandatory `RejectReason` (char 255) parameter; `approve`/`retrySync` return `$self`; the entity is read-only from the UI (no create/update/delete). **Partly met for the POC (2026-09-16):** the handler refuses an empty reason server-side. A metadata-level mandatory marker needs a root abstract entity, an abstract BDEF with `field ( mandatory : execute )` and a `deep parameter`, and is deferred until after the UI POC [source: abap-docs /abap-fiori-showcase/01_general_features #MandatoryParameter; /abap-docs-cloud/ABENBDL_ACTION_INPUT_PARAM, verified 2026-09-16 by my review] | UI contract (annotation.xml, mock metadata) |
|
|
| RAP-3 | `Status` carries a text element (`@ObjectModel.text.element`, `@UI.textArrangement: #TEXT_ONLY`) so the UI shows text, not codes | [source: fiori-mcp-server "Text and Text Arrangement", verified 2026-09-14] |
|
|
| RAP-4 | Semantic key `ItemNumber` (`@ObjectModel.semanticKey`); `Status` and `RequestedOn` sortable/filterable | UI default variant |
|
|
| RAP-5 | (Amended 2026-09-16.) Two service definitions, one binding each. `ZUI_ARENA_CHANGE_APPROVAL` exposes the UI projection as `ChangeApproval` through the OData V4 **UI** binding `ZUI_ARENA_CHANGE_APPR_O4`. `ZAPI_ARENA_CHANGE_APPROVAL` exposes the A2X projection through the OData V4 **Web API** binding `ZAPI_ARENA_CHANGE_APPR_A2X`. Binding names are 26 characters or fewer. The binding name sets the URL's first segment; hand back the UI binding's live `$metadata` to reconcile (V-2). The single-definition wording of 2026-09-14 could not hold, because a projection BDEF exposes only what it lists | [source: sap-docs sap-help loio 5717c0a1dafc4335add0207b81c39cef, 5f45f125dfe84c20beb18f5de1512f5a, verified 2026-09-14; binding-name limit: sap-docs sap-help loio 4bad0d7280b742a68dd2d42b1441f09a, verified 2026-09-16; abap-docs /abap-docs-cloud/ABENBDL_USE_PROJECTION, verified 2026-09-15] |
|
|
| RAP-6 | Worker-callable execution-state actions on the A2X binding — `markExecuting`, `markSynced` (sets `SapChangeNumber`), `markFailed` (sets `ErrorMessage`) — with instance feature control so the UI never offers Approve on an executing record | [source: abap-docs /abap-docs-cloud/ABENBDL_ACTIONS_FC, verified 2026-09-14] |
|
|
| RAP-7 | Staged payload (`SapPreview`) is `abap.string` — CDS char elements are capped at 1333 characters and truncation would break ARN-010 | [source: abap-docs /abap-docs-cloud/ABENCDS_SELECT_LIST_ENTRY_V2, verified 2026-09-14] |
|
|
| RAP-8 | Field `DecidedBy` (not `ApprovedBy`) holds approver or rejecter; semantic key `ItemNumber, ChangeType, ArenaEcoId` | UI contract |
|
|
|
|
## 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. **Superseded by ADR-004.**
|
|
- ADR-005 (2026-09-29) — **closes OQ-11**: Integration Suite native. Arena custom adapter (Adapter SDK) + iFlows for movement; human approval in SAP Build Process Automation; nothing on Cloud Foundry, nothing in ABAP. Narrows ADR-004's "side-by-side runtime" to mean "in Integration Suite". `worker/` becomes the specification, not a deliverable.
|
|
- 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
|
|
|
|
| ID | Item | Status |
|
|
|---|---|---|
|
|
| V-1 | Developer-extensibility access on the development tenant | **Closed 2026-09-15** — `my431353.s4hana.cloud.sap`: business user AZAW holds `ZBR_DEVELOPER` (SAP_BR_DEVELOPER template), `ZBR_ADMINISTRATOR_SW_DEV`, `ZBR_DEVELOPMENT_MANAGER_DIN` and five more (live: `sap-api users getRoles`, verified 2026-09-15). V-1b done 2026-09-15 (destination `0M7DEJI`, MCP lists it). Role correct (A4C catalogs). V-1b **closed 2026-09-15**: package `ZARENA_PLM` under `ZLOCAL`; probe class created and activated via ADT MCP |
|
|
| V-2 | Custom communication scenario can expose the approval BO's A2X service to the worker's technical user; and the Fiori app's annotation namespace, `_Type` entity-type suffix and UI-binding URL segment are reconciled from the live `$metadata` of the UI binding (decided 2026-09-14; the mock cannot verify this) | Open. **UI half in progress 2026-09-16:** live `$metadata` is captured in `docs/v2/zui_arena_change_appr_o4.metadata.xml`, and the UI host serves it to the developer user. The contract holds: all 17 property types, key, entity set, the three actions, and `RejectReason` non-nullable. Identity differs from the mock: namespace `com.sap.gateway.srvd.zui_arena_change_approval.v0001`, entity type `ChangeApprovalType`, URL segment `zui_arena_change_appr_o4`, and backend operation control via `__OperationControl`. **The app was reconciled 2026-09-16:** the dataSource targets `zui_arena_change_appr_o4`; the mock serves the live `$metadata` byte-for-byte; annotation targets use the live namespace and entity type; enablement is backend-owned; no old identity strings remain; lint, typecheck and `@ui5/linter` are clean; the mock server serves the service. Unverified until a live preview: the `DataFieldForAction` action-string form versus the backend's overload-specific `OperationAvailable` target. The A2X half (custom communication scenario, `-api` host) is still open. The service URL reported on `-api` carries `sap-client=080` |
|
|
| V-3 | On-stack Application Jobs vs worker-side polling for the Arena delta | Open — flow findings 2026-09-10: Arena's outbound-integration queue holds the cursor (`reconciled` flag) and is the clean delta mechanism; `/changes`-feed polling needs client-side date filtering (`docs/predecessor-flow.md` §1) |
|
|
| V-4 | Can a Claude Code agent outside the VS Code editor author ABAP source through the ADT MCP Server? | **Answered 2026-09-15: no.** `create_object` and the generators take structure, not source (live probe); SAP's editing MCP tool is planned for Public Edition 2702 [source: sap-docs loio 7f716223a88c40e0992777c8d9febccf, verified 2026-09-15]. Build plan: `x-ui-service` generator for the BO skeleton, source edits handed over as files for the VS Code editor until 2702 |
|
|
| OQ-5 | Long-term: move the sync executor on-stack (released ABAP APIs) vs keep it in the worker — worker initially | Open |
|
|
| OQ-6 | Webhook receiver hosting and auth for the worker on CF | Open |
|
|
| OQ-9 | Agent-side ABAP source read/write through the community `abap-adt-mcp` server (npm 2.1.0, a single maintainer, published 2026-09-16 01:04Z, SLSA provenance attested). It lists `getObjectSource`, `setObjectSource` and `activateObjects` next to 170 other tools, enforces `readOnly` / `allowedPackages` policy server-side, and signs in to Public Cloud through a one-time browser SSO. It would remove the manual paste step that SAP's ADT MCP forces (V-4). Checked 2026-09-16: a read-only smoke run with no login and no SAP call listed 173 tools and enforced a `ZARENA_PLM`-only read-only policy; nothing is registered. Adoption needs, in order: a source review of the package, because it would hold an SSO session into the tenant; a version pin; the development tenant only, never `my429480`; `allowedPackages: ["ZARENA_PLM"]`; read-only first; then a CLAUDE.md routing change | Open (2026-09-16), not blocking. I want it as the replacement for manual pasting; the read-only source review of the cached package (03:15) cleared every check it ran, observed as it ran. It stalled while collecting line citations for its report and was stopped at ~03:28, so no written report with file:line evidence exists. I accept it for the development tenant under the read-only-first configuration. Registered by hand in project scope at 03:37: stdio `npx -y abap-adt-mcp@2.1.0`, `MCP_READ_ONLY=1`, audit file on, `~/.abap-adt-mcp/systems.json` (development tenant `my431353`, client 100, SSO, `readOnly: true`, `allowedPackages: ["ZARENA_PLM"]`, mode 600). The other six project servers are intact. It connected after the restart, and its policy checked out live. **Parked 2026-09-16 03:49:** SSO needs an interactive sign-in inside the server's own Chrome, on the server's desktop (`:0`). That window is unreachable over my multi-hop SSH remote access; a DevTools relay was tried and dropped. The server stays registered but unused. It is revisited when a session at the server's desktop can complete one sign-in with "stay signed in", after which logins run unattended. The reentrance-ticket path was built and tested on 2026-09-18 (`tools/adt-reentrance-login/`) and **rejected on evidence**: the tenant ignores the ticket as both a `MYSAPSSO2` cookie and header, answering with its SAML redirect page (KNOWLEDGE 2026-09-18). Reviving OQ-9 requires capturing how ADT for VS Code exchanges the ticket. Until then, tenant work stays on SAP's ADT MCP plus editor paste. Until then, the UI leg continues with SAP's `adt-mcp` plus editor paste. The registration is run by hand, because Claude Code's permission guard refuses agent-side changes to its own MCP configuration (03:17, nothing written). The target is the development tenant, client 100, SSO login, first with `readOnly: true` + `allowedPackages: ["ZARENA_PLM"]` + `MCP_READ_ONLY=1`, then write enabled for `ZARENA_PLM` only |
|
|
| 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. | **Closed 2026-09-29 by ADR-005.** Neither of the options I framed survived the deciding criterion — a custom app on Cloud Foundry is discoverable only to whoever already knows the route to it, which is ADR-002's original objection relocated. The answer is Integration Suite native: an Arena adapter built with the Adapter SDK plus iFlows for the movement, and SAP Build Process Automation for the human approval. Decisive evidence: every mechanism `worker/` hand-rolled has an ADK facility (cluster lock, ADK persistency, user credentials, scheduler, connection status, tracing, endpoint visualization) [source: SAP Help *Adapter Development Process*, verified 2026-09-29]; and the ADK's Java/OSGi toolchain is not a new cost, because the AS/400 FetchAPI servlets are already Java and Java developers can be staffed in-house. |
|
|
| V-5 | POC: can an Adapter SDK sender adapter hold an Arena session (`POST /login` -> `arenaSessionId`, 25-minute TTL) under ADK cluster lock, and persist the delta cursor through ADK persistency? This is the first build and the gate on ADR-005. `worker/` is the behavioural specification | Open (2026-09-29) |
|
|
| V-6 | Where SAP Build Process Automation approval tasks surface for a business user, and whether they can be reached from the S/4HANA Fiori launchpad rather than only SAP Build's own inbox. This is what remains of the original acceptance test | Open (2026-09-29) |
|
|
| 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
|
|
|
|
| Work item | State |
|
|
|---|---|
|
|
| Package home + governance | 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 |
|
|
| 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 | 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 |
|