Files
arena-plm-fiori/PRD.md
T
2026-09-16 01:47:28 -07:00

14 KiB

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.

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)

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 │
└───────────────────────────────────────────────────────────────────────────┘

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.

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
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/zzui_arena_change_apprvl000_o4/srvd/sap/zzui_arena_change_apprvl000_o4/0001/ (binding ZZUI_ARENA_CHANGE_APPRVL000_O4, generated 2026-09-15, unpublished) expected namespace com.sap.gateway.srvd.zzui_arena_change_apprvl000_o4.v0001, alias SAP__self, entity ChangeApproval_Type/set ChangeApproval; confirm from live $metadata after publish (V-2); Fiori app still carries the pre-generation provisional name
Approval BO — Web API (A2X) binding (worker) V4 Web API binding ZAPI_ARENA_CHANGE_APPROVAL_A2X on definition ZAPI_ARENA_CHANGE_APPROVAL (pending: created after the A2X projection is active) custom communication scenario, technical user; namespace com.sap.gateway.srvd_a2x.zapi_arena_change_approval_a2x.v0001 expected; 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 → EXECUTING (amended 2026-09-14: a terminal success state is required so an approved record is never executed twice); 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) 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 Two service bindings on definition ZUI_ARENA_CHANGE_APPROVAL: OData V4 UI binding ZUI_ARENA_CHANGE_APPROVAL_O4 for the app and an OData V4 Web API binding for the worker; the binding name sets the URL first segment and the namespace; hand back the live $metadata of the UI binding to reconcile (V-2) [source: sap-docs sap-help loio 5717c0a1dafc4335add0207b81c39cef, 5f45f125dfe84c20beb18f5de1512f5a, verified 2026-09-14]
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.

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
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

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 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 — skeleton generated and active in ZARENA_PLM (2026-09-15, ATC clean); waiting on owner: paste docs/handover/rap/ sources in VS Code per its README, then I activate/ATC/create the A2X BDEF + binding; IAM app/catalog and publishing are the next brief
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