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>
92 KiB
CHANGELOG — arena-plm (standalone)
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/.envand the root.envnow carrySAP_API_URL,SAP_API_USERandSAP_API_PASSWORDforhttps://my429480-api.s4hana.cloud.sap; the eightCPI_*andARENA_*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.mdand.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.mdand marked ADR-002 superseded in its own file, including the note that its gate "confirm developer-extensibility access on my429480" was unanswerable as written.
- I pointed the shared CLI at the starter system's customizing tenant. Both
- 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 themc-s4hanadestination is out of reach; and the client-certificate path in the shared client looks for_shared/certs/az-api-user.crtand.key, which do not exist. No writes of any kind were issued to any tenant. - Affected:
_shared/.env,.env, both.bakfiles, 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-s4hanadestination 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
my429480andmy431353are tenants of the starter system.my429480is its customizing tenant (client 100);my431353is its development tenant (client 080). This package hadmy429480recorded as "productive" and treatedmy431353as 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 activatedZARENA_PLMobjects 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).
- Both
- 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 sourcescommit, and pushed it:468729e, 42 files, 4614 insertions, 1697 deletions, fast-forward ontoorigin/main. It carries the renamed RAP handover sources (the 11 generator-suffixedzz*000names replaced by the clean object names actually built on the tenant), theapp/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/mainnow 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/(Node, no dependencies): a one-shot loopback listener that captures an ADT reentrance ticket from theredirect-url=http://localhost:<port>/adt/redirectflow, writes it to a 0600 file, and probes how the tenant accepts it. It never prints, logs or passes the ticket through argv or the environment, and it parses the raw query itself, becauseURLSearchParamsturns a+in a ticket into a space and would corrupt it. Then I captured a real ticket and tested it:/sap/bc/adt/core/discoveryand an ABAP class source URL answered 200 with the same 3094-byte SAML redirect page for cookie transport, header transport and no credential, with and withoutsap-client=080. - Why:
abap-adt-mcp's browser SSO needs a window on the server's desktop, which is unreachable over this remote session (OQ-9). ADT for VS Code logs on with a reentrance ticket instead, so the question was whether that ticket can feed the server'ssso2(MYSAPSSO2 cookie) mode. - Affected: new
tools/adt-reentrance-login/,~/.abap-adt-mcp/systems.json(switched tosso2, then restored tosso), KNOWLEDGE.md, PRD OQ-9. - Decision: the approach is rejected on evidence. A reentrance ticket is
neither a logon-ticket cookie nor an assertion-ticket header on this
tenant, so
sso2cannot consume it. I restored the browser-login configuration, shredded the captured ticket, and kept the helper: it is the only piece that would still be needed if the exchange mechanism is ever identified. The next step, if this is revisited, is to capture what ADT for VS Code actually sends, not to guess header names. Tenant work continues on SAP's ADT MCP with editor paste, which is proven.
2026-09-16 — Worker leg active: approval BO complete on the development tenant
-
What changed:
- I activated W3 (A2X projection BDEF) and W4 (service definition
ZAPI_ARENA_CHANGE_APPROVAL). - I created and activated W5, the OData V4 Web API binding
ZAPI_ARENA_CHANGE_APPR_A2X, with binding typeOData V4 - Web API(create_objectreturned.srvb.json). fetch_services: serviceZAPI_ARENA_CHANGE_APPROVAL, version0001, V4,isPublished: false,bindingCategory: "1".- ATC over the five worker objects (worklist
12ACF6BD93811FE1ACBA776536DD5BD6): 0 errors and one priority-3 warning, W607 (+BDL 549) on BDEFZC_CHANGEAPPROVAL_A2X: "CDS annotation #CHECK … should be replaced with #MANDATORY".
[source: adt-mcp abap_activate_objects, abap_creation-create_object, abap_atc_get_result, abap_business_services-fetch_services on 0M7DEJI, verified 2026-09-16]
- I activated W3 (A2X projection BDEF) and W4 (service definition
-
Why: RAP-6. The worker needs create and the three execution-state actions through a Web API, separate from the read-only UI.
-
Affected: dev tenant
ZARENA_PLM(all 19 approval-BO objects now active), PRD RAP BO status, KNOWLEDGE.md. -
Decision: W5 stays unpublished. It is exposed to the worker's technical user through a custom communication scenario (V-2 A2X half), not through business-user access. I do not switch
@AccessControl.authorizationCheckfrom#CHECKto#MANDATORYnow: the warning does not block activation, and the change belongs with the OQ-8 authorization work, which revisits all three projection and root views together (the same annotation is inZR_CHANGEAPPROVALandZC_CHANGEAPPROVAL).
2026-09-16 — Worker leg: A2X projection view and access control active; A2X BDEF created
- What changed: I activated W1 (
ZC_CHANGEAPPROVAL_A2Xprojection view) and W2 (its access control); both answered "Activation successful." I then created W3, the projection BDEFZC_CHANGEAPPROVAL_A2X, empty (.bdef.abdl), after W1 was active [source: adt-mcp abap_activate_objects, abap_creation-create_object on 0M7DEJI, verified 2026-09-16]. W4 (service definition) is saved but not active. - Why: worker leg round 2 of the approval BO.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status. - Decision: W4 activates only after W3 is active. Then W5, the Web API binding, is created and verified unpublished.
2026-09-16 — Worker leg round 1 created; handover brought in line with live results
- What changed: after the expired VS Code ADT logon was restored, I
created W1 (
ZC_CHANGEAPPROVAL_A2Xview), W2 (its access control, withprotectedEntity) and W4 (service definitionZAPI_ARENA_CHANGE_APPROVAL) empty inZARENA_PLM[source: adt-mcp create_object on 0M7DEJI, verified 2026-09-16]. I also correcteddocs/handover/rap/: both service definition sources are comment-free, the README records the UI leg as active, ATC-clean and published, the activation-URI table marks the proven extensions (.tabl.ddic,.bdef.abdl,.srvb.json), and the worker-leg sequence is rewritten to two paste rounds. All 31 existing citations were preserved. - Why: worker (A2X) leg of the approval BO (RAP-6). The handover must not repeat today's failed activations.
- Affected: dev tenant
ZARENA_PLM,docs/handover/rap/, KNOWLEDGE.md. - Decision: pastes are opened manually from the ABAP workspace tree. I only
give the local source path and the
abap:/repotree-v1/…target, because editor tabs opened by URI cannot save. W5 uses binding typeOData V4 - Web API, the exact value the create metadata offers. W5 stays unpublished until the custom communication scenario brief (V-2).
2026-09-16 — Fiori app bound to the live RAP service identity (V-2 UI half)
-
What changed: I reconciled
app/with the published service.- Manifest dataSource and mock-server URL paths now use
/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/. - The mock
metadata.xmlis the live$metadata, byte-identical (sha256c13e86e1…, checked). - Mock rows carry
StatusText,LocalLastChangedAt,__OperationControlandSAP__Messages. - All annotation targets and action strings use namespace
com.sap.gateway.srvd.zui_arena_change_approval.v0001and entity typeChangeApprovalType.
A grep for the old identity over
app/(excludingnode_modules/dist) returns nothing. Lint, typecheck and@ui5/linterare clean. The mock server answers$metadataandChangeApprovalwith$filter,$countand__OperationControlselects. - Manifest dataSource and mock-server URL paths now use
-
Why: V-2 and ARN-007. The app must address the service that exists.
-
Affected:
app/(manifest,ui5-mock.yaml,ui5-local.yaml,annotation.xml, mock metadata and data, README), PRD V-2, new OQ-10, KNOWLEDGE.md. -
Decision:
- (1) Action enablement belongs to the backend. The mock's local
OperationAvailableoverrides went away with the mock metadata, andannotation.xmldeliberately defines none, because a local one would replace RAP's_it/__OperationControl/<action>[source: fiori-mcp-server "Action Control for Context-Dependent Actions", verified 2026-09-16]. - (2) No real backend is configured in the UI5 tooling yet. Any live
preview targets the UI host, never
-api. Its authentication type and client are verified before use, not assumed. - (3) UI annotation ownership is opened as OQ-10 rather than moved now: consolidating would drop i18n labels and action criticality and break the OPA section IDs mid-POC.
- (4)
dist/is stale and must be rebuilt before any deployment.
- (1) Action enablement belongs to the backend. The mock's local
2026-09-16 — Live $metadata captured: backend contract matches the app; identity names differ
-
What changed: the published UI service's
$metadatais captured indocs/v2/zui_arena_change_appr_o4.metadata.xml. It was copied from the browser on the UI hostmy431353.s4hana.cloud.sap; browser-decoded&characters were re-escaped. The-apihost refused the same request to a business user ("blocked by UCON").- Matches the app: all 17 app properties with identical EDM types
(
Edm.Booleanflags,Edm.Bytecriticality,Edm.DateTimeOffsetPrecision 7), keyID, entity setChangeApproval, and the actionsapprove,reject(RejectReason)(non-nullable) andretrySync. - Differs from the mock: namespace
com.sap.gateway.srvd.zui_arena_change_approval.v0001(from the service definition), entity typeChangeApprovalType, URL segmentzui_arena_change_appr_o4, extraStatusText/LocalLastChangedAt/__OperationControl/SAP__Messages, and backend-drivenCore.OperationAvailable.
I dispatched the app reconciliation.
- Matches the app: all 17 app properties with identical EDM types
(
-
Why: V-2. The app was built against a provisional mock identity, and only the live service can settle it.
-
Affected: PRD V-2,
app/(in progress), KNOWLEDGE.md. -
Decision: the live
$metadatareplaces the mock metadata and becomes the app's contract. Button enablement comes from the backend's__OperationControlrather than localIsApprovable/IsRetriableoverrides, unless the Fiori docs show that breaks something. Any non-mock backend configuration points at the UI host, never-api. Earlier notes claiming the binding name sets the namespace are superseded (KNOWLEDGE 2026-09-16).
2026-09-16 — Approval UI service published on the development tenant
- What changed: the OData V4 UI binding
ZUI_ARENA_CHANGE_APPR_O4is published. The ADT for VS Code Publish code lens gave no visible confirmation, so I verified it live:fetch_servicesreportsisPublished: true, andfetch_service_informationreturnshttps://my431353-api.s4hana.cloud.sap/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/?sap-client=080with entity setChangeApproval[source: adt-mcp abap_business_services-fetch_services, fetch_service_information on 0M7DEJI, verified 2026-09-16]. - Why: RAP-5. The Fiori app cannot bind to an unpublished service.
- Affected: PRD RAP BO status, V-2, KNOWLEDGE.md.
- Decision: the URL path is exactly the designed one, so no binding change
follows. The app's V-2 reconciliation (dataSource first segment,
namespace, annotation targets, EDM types) is done against the live
$metadata, never inferred. The service reports client 080, so the client value in any tool configuration comes from the live system.
2026-09-16 — UI leg active: approval BO and OData V4 UI service built on my431353
-
What changed:
- U13, the service definition
ZUI_ARENA_CHANGE_APPROVAL, activated after I re-saved it without its header comment. The same definition failed with the comment and succeeded without it, so the comment was the blocker; the missing-draft message is not. - I created U14, the OData V4 UI binding
ZUI_ARENA_CHANGE_APPR_O4(create_objectreturned.srvb.json), and activated it. - ATC over all 14 UI-leg objects: 0 errors, 0 warnings, 43 infos
(worklist
12ACF6BD93811FE1ACB8096AC6763BD6). fetch_services: serviceZUI_ARENA_CHANGE_APPROVAL, version0001, OData V4, unpublished.
[source: adt-mcp abap_activate_objects, abap_creation-create_object, abap_atc_get_result, abap_business_services-fetch_services on 0M7DEJI, verified 2026-09-16]
- U13, the service definition
-
Why: RAP-1..8 and the ARN-007 acceptance path. The service must exist before the app can bind to it.
-
Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, KNOWLEDGE.md, handover README (both SRVD sources still carry header comments, and U9 still says.bdef.json). -
Decision: the service alias equals the definition name and the version is
0001. Publishing therefore yields/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/, as designed, so no rename is needed before publishing. The 43 ATC infos are reviewed in the ADT ATC view (the MCP returns only totals); infos do not gate publishing. I correct the handover README in one pass before the worker leg: comment-free SRVD sources and BDEF.bdef.abdlURIs.
2026-09-16 — Wave D: projection BDEF, access control and metadata extension active; service definition refused
-
What changed: I activated U9 (projection BDEF
ZC_CHANGEAPPROVAL), U11 (its access control) and U12 (its metadata extension); each answered "Activation successful." Activating U13, the service definitionZUI_ARENA_CHANGE_APPROVAL, answered "Activation failed" with two messages and no severity:- "Comments are not supported and will be deleted on save" (Ln 1, the handover header block comment)
- "oData V4 services with no draft capability will be primarily READ-ONLY" (Ln 21). The BO has no draft, by design.
CDS SDL allows comments as a language rule [source: abap-docs /abap-docs-cloud/ABENCDS_F1_SDL_SYNTAX, ABENCDS_GENERAL_SYNTAX_RULES, verified 2026-09-16], so the refusal comes from the service definition tooling, not the language. U14 (the binding) was not created.
-
Why: wave D of the UI leg.
-
Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, KNOWLEDGE.md. -
Decision: I re-save U13 with only its definition (annotation,
define service,expose) and no header comment, then activate again. If it still fails with only the draft message, that message is blocking, and I read its severity in the editor's Problems view before changing anything about draft.
2026-09-16 — abap-adt-mcp parked: SSO cannot complete over remote access
- What changed: with
SAP_BROWSER_PATHset, the SSO login launched Chrome with a dedicated profile on the server's desktop display and waited on the Microsoft Entra sign-in page. The login does not use a localhost redirect: SAML returns to the tenant, and the server harvests the session cookies from its own Chrome over the DevTools protocol (dist/lib/browserLogin.js). I tried a localhost-only DevTools relay on a fixed port for remote interaction. It is not workable through multi-hop SSH proxies, so I stopped it and closed the login browser. No login happened. The server remains registered, read-only. - Why: the sign-in has to happen inside the server's browser, and that browser is on a desktop I cannot reach from this remote session.
- Affected: PRD OQ-9, KNOWLEDGE.md.
- Decision: I park
abap-adt-mcprather than remove it. One sign-in at the server's desktop, with "stay signed in", should let later logins run unattended in the invisible browser; that is unverified. The UI leg finishes on the proven path: SAPadt-mcpfor create and activate, source pasted in the VS Code editor. Four wave-D sources, one binding and a publish remain.
2026-09-16 — abap-adt-mcp connected; SSO blocked on browser detection
- What changed: after the restart,
abap-adt-mcpconnected.listSystemsshowed exactly one destination,MY431353(client 100, SSO), with policyreadOnly: trueandallowedPackages: ["ZARENA_PLM"]. The first SAP call (classIncludesonZBP_R_CHANGEAPPROVAL) failed before any login: "No Chrome/Edge/Brave found for SSO login." The server's browser detection covers only macOS paths (KNOWLEDGE 2026-09-16). - Why: SSO login is the gate to the read-only Local Types check.
- Affected: project MCP registration (env), KNOWLEDGE.md.
- Decision: the registration gains
SAP_BROWSER_PATH=/usr/bin/google-chromeand nothing else changes. This is a manual step, like the original registration.
2026-09-16 — abap-adt-mcp registered read-only in project scope
- What changed:
abap-adt-mcpis registered in the project.mcp.json(git-ignored, mode 600). It runs over stdio asnpx -y abap-adt-mcp@2.1.0withMCP_READ_ONLY=1, an audit log at~/.abap-adt-mcp/audit.jsonl, and the desktop display variables for the SSO browser. Its systems file lists only the development tenantmy431353, client 100, SSO, withpolicy.readOnly: trueandallowedPackages: ["ZARENA_PLM"]. The six existing project servers are unchanged,adt-mcpincluded. - Why: OQ-9. Agent-side source read and write would replace manual pasting for the remaining RAP objects.
- Affected: project MCP configuration, PRD OQ-9.
- Decision: the first use is a read-only
getObjectSourceof the behavior pool's Local Types include. That check settles whether wave C's activation proved the handler constructs. Write access is enabled only after that read succeeds. The CLAUDE.md MCP routing table changes only once the server has written and activated an object successfully.
2026-09-16 — abap-adt-mcp source review: all checks cleared; written report not produced
- What changed: the read-only source review of
abap-adt-mcp2.1.0 cleared every check it ran (install scripts, network egress, credential and session storage, policy enforcement, dangerous primitives), observed as it ran. It then stalled while collecting line citations, consumed its budget, and was stopped at ~03:28, so no written report with file:line evidence exists. As of 03:30 the package is not registered, no~/.abap-adt-mcpconfiguration exists, and no login has happened. The tenant state is unchanged: waves A–C are active, and wave D (U9, U11, U12, U13) exists empty. - Why: OQ-9 was gated on this review.
- Affected: PRD OQ-9.
- Decision: I accept the review for the development tenant only, under the
read-only-first configuration (pinned 2.1.0,
readOnly: true,allowedPackages: ["ZARENA_PLM"],MCP_READ_ONLY=1, audit file on). Registration is run by hand. The missing citations mean this clearance does not extend to the productive tenant. Any future review brief is scoped to named files with a size budget, because this one ran unbounded.
2026-09-16 — abap-adt-mcp registration is a manual step; read-only first
- What changed: an attempt to write
~/.abap-adt-mcp/systems.jsonand to registerabap-adt-mcpin the project MCP configuration was refused by Claude Code's permission guard as self-modification. Nothing was written. I confirmed the development tenant logs in on client 100. The package's SSO login launches Chrome visibly (headless: false), so the MCP server needs the desktop session's display variables. - Why: I want agent-side source writes (OQ-9), and registration is the gate.
- Affected: PRD OQ-9, project
.mcp.json(only once registered by hand), CLAUDE.md MCP routing (only once adopted). - Decision: the registration is run by hand, not routed around the guard.
The first configuration is read-only (
policy.readOnly: true,allowedPackages: ["ZARENA_PLM"],MCP_READ_ONLY=1), limited to the development tenant, and pinned to 2.1.0. The first login waits for the source review verdict. Writes are enabled only after a read-onlygetObjectSourceon the behavior pool's Local Types include succeeds.
2026-09-16 — Community abap-adt-mcp smoke-tested read-only; not adopted yet (OQ-9)
- What changed: I ran
abap-adt-mcp2.1.0 once throughnpxover stdio. It ran withMCP_READ_ONLY=1and a scratchpad systems file listing only the development tenant, restricted toZARENA_PLM.initializeandtools/listanswered: 173 tools, including source read/write and activation.listSystemsshowed the read-only, package-restricted policy enforced. There was no login and no SAP call. Nothing was registered in any Claude Code or project configuration (verified 03:12). The package remains in the local npx cache. I opened OQ-9. - Why: SAP's ADT MCP cannot write source (V-4), so every RAP source is pasted by hand. A server that can read and write source would remove that step and would also let me read the behavior pool's Local Types include directly.
- Affected: PRD OQ-9, V-4 (possible alternative), CLAUDE.md MCP routing (a change only on adoption).
- Decision: I do not adopt it mid-build. Only four pastes and one publish
remain on the UI leg. The package was published the same day, by one
maintainer, and would hold a browser SSO session into the tenant, so it
gets a source review before any login. I run it read-only first. The
productive tenant
my429480is never listed in its systems file.
2026-09-16 — Wave C active: behavior pool and UI projection view live; wave D created
- What changed: I activated U6 (base BDEF) and U7 (behavior pool
ZBP_R_CHANGEAPPROVAL) together in one call, then U8 (UI projection viewZC_CHANGEAPPROVAL). All answered "Activation successful." The locally cached class metadata shows the class active with categorybehaviorPool. I then created wave D empty: U9 projection BDEFZC_CHANGEAPPROVAL(.bdef.abdl), U11 access control (.dcls.acds), U12 metadata extension (.ddlx.acds) and U13 service definitionZUI_ARENA_CHANGE_APPROVAL(.srvd.acds).SRVD/SRValso offers an optionalreferencedObjectcreate field [source: adt-mcp abap_activate_objects, abap_creation-create_object, get_object_type_details on 0M7DEJI, verified 2026-09-16]. - Why: wave C of the UI leg. Wave D is the last paste group before the UI binding.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, handover README (BDEF extension.bdef.abdlfor U9 and W3; SRVD tag list), KNOWLEDGE.md. - Decision: I do not record
OPTIONS PRIVILEGED ACCESS,%op-%action-<name>on MODIFY response rows or@status-rejectedas proven yet. Activation returns no warnings, and no source says whether a behavior pool with an empty Local Types include fails activation. I confirm the handler source is in the Local Types include in the editor first. Failing that, the first action call at U15 proves it at runtime. I correct the handover README's BDEF extension and SRVD tag list in one pass after the UI leg, rather than interrupting the paste session.
2026-09-16 — Wave B active: base behavior definition and root access control live
- What changed: I activated U10, the access control
ZR_CHANGEAPPROVAL, and U6, the managedstrict ( 2 )behavior definitionZR_CHANGEAPPROVAL. Both answered "Activation successful." U6 activated through its.bdef.abdlURI on the first attempt, before its behavior pool class existed. That also proves the three action-parameter entities it references are active. I then created wave C empty: U7, the behavior poolZBP_R_CHANGEAPPROVAL(create_objectreturned only the global.clas.abappath, no local-types include), and U8, the UI projection viewZC_CHANGEAPPROVAL(.ddls.acds) [source: adt-mcp abap_activate_objects, abap_creation-create_object on 0M7DEJI, verified 2026-09-16]. - Why: wave B of the UI leg.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, handover README (the BDEF activation extension is.bdef.abdlfor U6, U9 and W3, and the U6 fallback was not needed), KNOWLEDGE.md. - Decision: now that an empty
ZBP_R_CHANGEAPPROVALexists, I activate U6 and U7 together in one call, so the BDEF is never checked against a class that is not yet a behavior pool. The activation tool returns no warnings, so warnings about the four unmapped calculated fields are checked in the editor's Problems view rather than assumed absent. I locate the local-types include live, after the global class part is saved.
2026-09-16 — Wave A active: table, parameter entities and root view live; wave B created
- What changed:
- I activated U1
ZCHANGEAPPROVAL, U2–U4 (the three action-parameter entities) and U5ZR_CHANGEAPPROVALonmy431353. Each activation answered "Activation successful.", and the tool returned no warnings. - The table activates through its
.tabl.ddicURI;.tabl.jsonholds only header metadata. - U5's
cast( case … as abap_boolean preserving type )was accepted, so the fallback is not needed [source: adt-mcp abap_activate_objects on 0M7DEJI, verified 2026-09-16]. - I then created wave B empty: U6, the managed BDEF
ZR_CHANGEAPPROVAL(create_objectreturned…/zr_changeapproval.bdef.abdl), and U10, the access controlZR_CHANGEAPPROVAL(…/zr_changeapproval.dcls.acds, withprotectedEntity).
- I activated U1
- Why: wave A of the UI leg. Creating the U6 BDEF requires the root view to be active, and it validated, which confirms U5 is active.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, the handover README activation table (TABL now proven; BDEF extension open), KNOWLEDGE.md. - Decision: BDEF source is pasted into
.bdef.abdl, not.bdef.json. At U6 activation I try the.bdef.abdlURI first and fall back to.bdef.json, which activated a generator BDEF on 2026-09-15. The README activation table is corrected once U6 proves the extension. Activation gives no direct active/inactive readback, so proof is indirect: U6's activation is the first test of U2–U4, because U6 names them as action parameters.
2026-09-16 — Review fixes applied to the handover; duplicate checks read with privileged access
-
What changed: all four remaining review fixes are in
docs/handover/rap/.use etagsits in the entity header of both projection BDEFs.retrySyncwrites APPROVED, so EXECUTING is written only bymarkExecuting.- All six action handlers set
%fail-causeand%op-%action-<name>, merge the internal UPDATE's failed and reported rows, and return results only for keys that did not fail. - The base BDEF declares
validation checkDuplicate on save { create; }. Its handler refuses a second non-REJECTED record with the sameItemNumber+ChangeType+ArenaEcoId, within the request or against persisted rows.
The base BDEF and README carry the OQ-8 note that
authorization master ( none )is not final. The table's paste target is.tabl.ddic; its activation extension is still pending live proof. Two of my working sessions wrote these files concurrently between 02:36 and 02:43. I confirmed the result is consistent and stable (content unchanged over 45 seconds at 02:45, no duplicate governance entries). This session is now the only one driving the build. -
Why: review findings B1, M1, m1 and m4 (entry below). Every one must be in the source before its object is pasted.
-
Affected: handover U6, U7, U9, W3, U1 header, README; PRD RAP BO status.
-
Decision: the duplicate check reads
ZR_CHANGEAPPROVALwith privileged access. The view is access-controlled, and a handlerSELECTon it without privileged access breaks the RAP implementation rules [source: sap-docs sap-help abaprap_impl_rules; abap-docs /abap-docs-cloud/ABAPSELECT_PRIVILEGED_ACCESS, verified 2026-09-16]. The validation's failed rows carry onlycause-unspecific, the only cause validations may use (same rules page). Three constructs are syntax I prove only at tenant activation, each with a documented fallback:OPTIONS PRIVILEGED ACCESS(fallbackFROM … WITH PRIVILEGED ACCESS),%op-%action-<name>on MODIFY response rows, andpreserving typeon the U5 casts.
2026-09-16 — Root view U5 final: derived booleans cast as a whole
- What changed: in
zr_changeapproval.ddls.asddls,IsApprovableandIsRetriableare nowcast( case status when … then abap.char'X' else abap.char' ' end as abap_boolean preserving type ). The file header records why: typedabap.charliterals make the CASE result CHAR(1) [source: abap-docs /abap-docs-cloud/ABENCDS_TYPED_LITERAL_V2, verified 2026-09-16], andABAP_BOOLEANis "of data typeCHARof length 1" [source: abap-docs /abap-docs-standard/ABENDATAOBJECTS_TRUE_VALUE_GUIDL, verified 2026-09-16], sopreserving typematches exactly. U5 is cleared for paste. - Why: review finding (4). A cast inside a CASE branch drops the data element semantics.
- Affected: handover U5, wave A paste.
- Decision: if activation still rejects
preserving type, I drop only that addition, not the outer cast. I finalized U5 ahead of the remaining correction work so wave A is not held up. Two concurrent corrections collided on this file; each later brief names file ownership explicitly.
2026-09-16 — App documentation aligned to retry → APPROVED
- What changed: I updated the four statements of the retry transition in
app/(README, both i18n#XBUTcomments, the mockmetadata.xmlcomment) from FAILED → EXECUTING to FAILED → APPROVED. No labels, annotations, manifest or mock data changed.npm run lintandnpm run ts-typecheckpass. - Why: ARN-002 was amended today; the app's documentation must not describe the old state machine.
- Affected:
app/README.md,app/webapp/i18n/i18n.properties,app/webapp/i18n/i18n_en.properties,app/webapp/localService/mainService/metadata.xml, KNOWLEDGE.md. - Decision: I do not add a mock
executeActionhandler to show the new transition. The mock server ignores actions (KNOWLEDGE 2026-09-16), and the live RAP service replaces the mock at V-2 within this build, so a mock-only transition would be throwaway work. The remoteui5-mcp-servercannot lint local files; I lint UI5 code locally until that changes.
2026-09-16 — Pre-paste SAP review: one blocker, retry semantics corrected, authorization opened
- What changed: I reviewed all 18 handover sources read-only against ABAP
Cloud docs, clean-core release states, the PRD and the app contract. The
app contract holds (17 properties, 3 actions, entity set
ChangeApproval, no UI create/update/delete), and all 11 referenced SAP objects are clean core level A [source: sap-released-objects sap_check_clean_core_compliance, verified 2026-09-16]. The review found:- One blocker:
use etagsat in the body of both projection BDEFs, but it belongs in the entity header [source: abap-docs /abap-docs-cloud/ABENBDL_CHARACTER_PROJECTION, verified 2026-09-16]. - Two majors: retry semantics and missing per-operation authorization.
- Four minors. I dispatched corrections before any affected source reached the tenant.
- One blocker:
- Why: every defect caught here saves a paste-and-activate round trip against the live tenant, and two of them were correctness defects, not syntax.
- Affected:
docs/handover/rap/(U5, U6, U7, U9, W3, README), PRD ARN-002, RAP-2, new OQ-8,app/documentation comments, KNOWLEDGE.md. - Decision:
- (1)
retrySyncgoes FAILED → APPROVED, clearsErrorMessage, and the worker re-claims the record throughmarkExecuting. The earlier FAILED → EXECUTING could not be claimed, becausemarkExecutingaccepts only APPROVED. Working around that would make a retried record indistinguishable from one another run is executing, which is the double-write risk ARN-006 exists for. - (2) Duplicate staging is refused on create: a
checkDuplicatevalidation on the semantic key while a non-REJECTED record exists. Webhook and delta poll can both deliver the same ECO, and I will not leave idempotency to the executors alone. - (3) Action handlers honor the RAP implementation contract (
%fail,%op, propagated UPDATE failures, results only for successful keys), so the worker cannot read a failedmarkSyncedas success. - (4) The derived boolean flags cast the whole CASE to
abap_boolean, because a cast inside a CASE branch drops the data element semantics [source: abap-docs /abap-docs-cloud/ABENCDS_CAST_EXPRESSION_V2, verified 2026-09-16]. - (5) Deferred: a metadata-level mandatory
RejectReason, until after the POC (server-side enforcement exists). - (6) Opened: OQ-8.
authorization master ( none )stays for the dev-tenant POC only and must be replaced before business roles get the app.
- (1)
2026-09-16 — Wave A created: table, parameter entities, root view exist empty
- What changed: I created U1
ZCHANGEAPPROVAL(TABL) and U2–U5ZD_CHANGEAPPROVAL_REJECTP,ZD_CHANGEAPPROVAL_SYNCEDP,ZD_CHANGEAPPROVAL_FAILEDPandZR_CHANGEAPPROVAL(DDLS) inZARENA_PLM. They are inactive and have no source.abap_transport-getansweredisRecordingRequired: false. Each object passed validation and creation with the handover JSON unchanged. The table's returned URI ends in.tabl.ddic, not the.tabl.jsonthat activated a generator-created table on 2026-09-15 [source: adt-mcp abap_creation-create_object on 0M7DEJI, verified 2026-09-16]. - Why: wave A of the UI leg. The sources are pasted next.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, handover activation URI table (TABL extension open). - Decision: I activate U1 with the URI
create_objectreturned (.tabl.ddic) and fall back to.tabl.json. The handover URI table is corrected once activation proves which one works.
2026-09-16 — Package recreated; UI-leg build started in waves
- What changed: package
ZARENA_PLMexists again underZLOCAL. ADT MCP validation ofZCHANGEAPPROVALin it succeeded (live, 02:27). I started wave A of the UI leg: U1–U5 (table, the three action-parameter entities, root view) are created empty so their sources can be pasted. I also read the create fields for classes, access controls and metadata extensions live. Those were the three types the handover had marked unconfirmed. Metadata extension names allow 40 characters. Access controls and metadata extensions take an optional protected/extended entity (KNOWLEDGE 2026-09-16). - Why: the from-scratch build (OQ-7) is unblocked. The build moves in waves bounded by activation dependencies: BDEF creation needs its root view active, and the binding needs its service definition active. Each wave asks for one paste session per group, not one per file.
- Affected: dev tenant
ZARENA_PLM, PRD RAP BO status, KNOWLEDGE.md. - Decision: waves are A = U1–U5 (create, paste, activate), B = U6 base BDEF, C = U7 behavior pool, D = U8 projection view + U10 root access control, E = U9 projection BDEF + U11 + U12 + U13, F = U14 binding with the service-alias check. Nothing is activated before its source is pasted.
2026-09-16 — Handover regenerated under clean names; binding names cut to SAP's 26-character limit
- What changed: I regenerated
docs/handover/rap/for a build from an empty package. Eleven source files were renamed to the clean object names, every internal reference was updated, and the README was replaced with a create → paste → activate sequence per object. The UI service definition exposes onlyChangeApproval. A scripted comparison against the app's mockmetadata.xmlconfirms that the UI projection carries all 17 app properties plusapprove,rejectandretrySync. The build splits into a 14-source UI leg and a 4-source worker leg. ThemarkSynced/markFailedparameter entities move into the UI leg, because the base BDEF references them and they must be active first. I amended RAP-5 to two service definitions with one binding each, and updated both PRD interface-contract rows. A read-only SAP review of the 18 sources is running before the paste session. - Why: the tenant package is empty, so the handover's generator inventory
and
ZZ…000targets no longer existed. SAP Help gives a maximum of 26 characters for service binding names, the same in ABAP Cloud, SAP Cloud Platform and ABAP Platform 2021 [source: sap-docs sap-help loio 4bad0d7280b742a68dd2d42b1441f09a, f3e608ace2a64aada33bdd3e2419113a, 777e027f61c3490dba0433443d9143a6, verified 2026-09-16]. The ADT MCP's create metadata allows 30, and generator bindings of 29–30 characters activated on 2026-09-15, but none was ever published. No source says whether publishing tolerates more than 26. - Affected: PRD RAP-5, the two approval-BO interface-contract rows, RAP BO
status,
docs/handover/rap/, V-2 (the app's dataSource URL, mock namespace and annotation targets now carry a planned difference), KNOWLEDGE.md. - Decision: the bindings are
ZUI_ARENA_CHANGE_APPR_O4(24) andZAPI_ARENA_CHANGE_APPR_A2X(26). The service definitions keepZUI_ARENA_CHANGE_APPROVALandZAPI_ARENA_CHANGE_APPROVAL. I chose the documented limit over the tool's undocumented allowance, because a refusal at publish would come after the whole UI leg and need a delete in ADT to recover. The app edit this causes is one URL segment plus the namespace, both already scheduled for V-2 reconciliation against live$metadata, so I defer it to that brief instead of changing the app twice. The derived-field EDM types (StatusCriticalityas INT1,abap_booleanflags,utclong,sysuuid_x16) stay unverified until live$metadataexists; they are not assumed.
2026-09-16 — Deletion verified live: package ZARENA_PLM is gone; name limits confirmed
- What changed: with the ADT MCP back online I probed
my431353read-only.abap_creation-run_validationanswers "Package 'ZARENA_PLM' does not exist" for tables, data definitions and classes, the same as a nonexistent control package. The deletion removed the package itself, not just its contents.abap_creation-get_object_type_detailsgives the maximum name lengths: database table 16; data definition, service definition, service binding and behavior definition 30 [source: adt-mcp abap_creation-get_object_type_details on 0M7DEJI, verified 2026-09-16]. - Why: the from-scratch build starts from the package, and every clean name had to fit its limit before any object is created.
- Affected: PRD RAP BO status,
docs/handover/rap/README.md(step 0 is now "recreate the package"), KNOWLEDGE.md. - Decision: I recreate
ZARENA_PLMunderZLOCALunder the same name, so every activation URI pattern verified on 2026-09-15 stays valid. All clean names fit (ZCHANGEAPPROVAL15,ZUI_ARENA_CHANGE_APPROVAL_O428).ZLOCALmeans no transport request on every create while I prototype. It is not a dead end for production: a package can be reassigned fromZLOCALtoZCUSTOM_DEVELOPMENT(transport layer YDEV) later, though not the reverse [source: sap-docs sap-help loio a0d80f14fcb74cb1ac8fb6f3d9ad48cc (2608), verified 2026-09-15]. I make that move once the approval app works end to end on the development tenant.
2026-09-16 — Tenant package emptied; from-scratch build under names that match the Fiori app
- What changed: the
ZARENA_PLMcontents onmy431353were deleted in ADT. This includes both generator sets and the empty hand-created objects. I have not yet verified the deletion live (the ADT MCP is offline), and the package's own survival is unconfirmed. I closed OQ-7 and dispatched a regeneration ofdocs/handover/rap/under the clean names. - Why: the Fiori app binds to
/sap/opu/odata4/sap/zui_arena_change_approval_o4/srvd/sap/zui_arena_change_approval/0001/, entity setChangeApproval, and actionsapprove,rejectandretrySync(app/webapp/manifest.json, mockmetadata.xml). A Fiori app runs against a replacement service only if the entity set names, properties and actions match [source: fiori-mcp-server search_docs "Replacing OData Service in an Adaptation Project", verified 2026-09-16]. With the package empty, no leftover objects compete for these names. - Affected: PRD OQ-7 (closed), RAP BO status,
docs/handover/rap/(all 19 sources and the README), V-2 (the service identity is now designed to match the app instead of reconciled after the fact). - Decision: no generator this time, because it forces a
ZZprefix and a000suffix (KNOWLEDGE, 2026-09-15). I create each object through the ADT MCP under its final name: tableZCHANGEAPPROVAL,ZR_CHANGEAPPROVAL,ZBP_R_CHANGEAPPROVAL,ZC_CHANGEAPPROVAL, SRVDZUI_ARENA_CHANGE_APPROVAL, SRVBZUI_ARENA_CHANGE_APPROVAL_O4. The A2X names are unchanged. The UI leg (about 13 sources) is built and verified against the app before the worker leg starts.
2026-09-16 — Tenant state corrected: two generator sets, no designed logic deployed; naming decision opened
- What changed: a live ATC run over
ZARENA_PLMreturned 43 objects, not the 12 my 2026-09-15 handover README lists. The package holds two defaultx-ui-servicegenerator sets side by side: theZZ…000set (ZZCHNGPPROVAL000,ZZR_/ZZC_CHANGEAPPROVAL000, bindingZZUI_ARENA_CHANGE_APPRVL000_O4) and a set without the suffix (ZZCHANGEAPPROVAL,ZZR_/ZZC_CHANGEAPPROVAL, bindingZZUI_ARENA_CHANGE_APPROVAL_O4). Each set has its own behavior pools and SAP object types. It also holds the five empty, inactive hand-created objects and the probe class. None of the six actions, the status machine, or the feature control exists in any tenant object. The designed source lives only indocs/handover/rap/, which is now committed and pushed (f8b45ea). My most likely explanation for the second set is an earlier generator run that I never recorded; I cannot confirm it, because the ADT MCP has no read tool. - Why: my 2026-09-15 entry and the PRD status described a clean skeleton that was ready for a paste session. Following them would put the sources into objects whose names the Fiori app does not bind to.
- Affected: PRD status (RAP BO → blocked on OQ-7), new OQ-7,
docs/handover/rap/README.md(its object inventory is stale), the Fiori app's V-2 service identity. - Decision: none yet. I recommend building under clean names that match the
app, next to the unused sets, and deferring deletion. The two sets are
unpublished, their
ZZnames do not collide with the clean set, and deleting them needs Eclipse ADT, which is not set up. Of the 19 sources, 13 serve the UI milestone. The six A2X-leg files wait until the app runs against the real service.
2026-09-15 — abapGit researched: not required for ADT for VS Code; viable as a bulk source-load path
- What changed: I verified that abapGit is neither required nor used by SAP's
ADT for VS Code; the belief traces to the community
vscode-abap-remote-fsextension on this host. In S/4HANA Cloud Public Edition, abapGit is SAP's supported fork reachable only through the Eclipse ADT "abapGit Repositories" plug-in, and SAP lists it as the initial-transfer tool for developer extensibility code in every delivery model [source: sap-docs sap-help loio ec943b4ee4ac4dfdac47081d1d3e4019 "Overview of ABAP Lifecycle Management Options", verified 2026-09-15]. Recorded as a KNOWLEDGE landmine. - Why: the RAP handover (19 ready-to-paste sources under
docs/handover/rap/) is blocked on source entry because the ADT MCP Server cannot write source (PRD V-4). abapGit pull from a repository is the one SAP-standard bulk alternative to pasting file by file in the editor. - Affected: KNOWLEDGE.md, PRD V-4 (an option, not a change of decision).
- Decision: keep VS Code editor paste as the default for this first BO (19 files, one-off); evaluate the abapGit pull path only if a second bulk load is needed, because it requires Eclipse ADT plus an abapGit-formatted repository with the metadata files the serializer expects.
2026-09-15 — Approval BO skeleton generated on my431353; source handover written
- What changed: I generated the Arena change-approval RAP business object
into
ZARENA_PLMwith SAP's "OData UI Service from Scratch" generator (transactional without draft, 13 business fields incl.SapPreviewas string): tableZZCHNGPPROVAL000, root view/BDEF/DCLZZR_CHANGEAPPROVAL000, behavior poolZZBP_R_CHANGEAPPROVAL000, UI projectionZZC_CHANGEAPPROVAL000(+ BDEF, metadata extension, DCL, pool), service definition + OData V4 UI bindingZZUI_ARENA_CHANGE_APPRVL000_O4(unpublished), SAP object type/node type — all active, ATC: 0 findings on 12 objects (live, 2026-09-15). For the worker I created a separate A2X projectionZC_CHANGEAPPROVAL_A2X(+ DCL) and service definitionZAPI_ARENA_CHANGE_APPROVAL, plus three abstract entities for action parameters; these exist empty and inactive. The A2X BDEF and the Web API bindingZAPI_ARENA_CHANGE_APPROVAL_A2Xcannot be created until their referenced objects are active. Nineteen ready-to-paste source files and an ordered paste-and-activate sequence are indocs/handover/rap/. - Why: RAP-1..8; the MCP creates structure but not source (V-4), so logic — six actions with instance feature control, status transitions, the on-modify determination, text/criticality/semantic-key annotations — is delivered as source for the VS Code editor.
- Affected: dev tenant
ZARENA_PLM; PRD interface contracts (binding names now real), RAP-5/RAP-6 wording, status; KNOWLEDGE (generator landmines). - Decision: (1) two service definitions, not one — a projection BDEF exposes
only what it lists, so sharing one definition would hand the UI create and
the worker actions [source: abap-docs /abap-docs-cloud/ABENBDL_USE_PROJECTION,
verified 2026-09-15]; the UI gets
ZZUI_ARENA_CHANGE_APPRVL000_O4, the workerZAPI_ARENA_CHANGE_APPROVAL_A2X. (2)markSynced/markFailedtake abstract-entity parameters, since action input must be an abstract entity or DDIC type [source: abap-docs /abap-docs-cloud/ABENBDL_ACTION_INPUT_PARAM, verified 2026-09-15]. (3) Derived fields (StatusCriticality,StatusText,IsApprovable,IsRetriable) are CASE expressions in the root view, not persisted — falsifiable at activation; fallback documented in the file header. (4)authorization master ( none ): IAM catalog + DCL are the only access control (ADR-002) [source: abap-docs /abap-docs-cloud/ABENBDL_AUTHORIZATION, verified 2026-09-15]. (5) Generator naming (ZZ…000) is kept; the Fiori app reconciles from live$metadataat V-2.
2026-09-15 — Write path proven: probe class created and activated in ZARENA_PLM; RAP build dispatched
- What changed: after the owner created development package
ZARENA_PLMunderZLOCALin Eclipse ADT, the ADT MCP createdZCL_ARENA_V4_PROBEthere and activated it (no transport, as SAP Help states forZLOCALsub-packages from 2508 [source: sap-docs loio a0d80f14fcb74cb1ac8fb6f3d9ad48cc, verified 2026-09-15]). Object-type probes: DDLS/BDEF/SRVB/TABL creation takes metadata only (name, package, referenced object, BDEF root entity and implementation type, SRVB binding type incl. "OData V4 - Web API"), never source. I grantedrap-developertheadt-mcptools and pointed it at the dev tenant, then dispatched the approval-BO build. - Why: V-1b and V-4 are closed; the RAP track (RAP-1..8) has no remaining gate.
- Affected: PRD V-1b/V-4 (closed), status RAP BO (In progress),
.claude/agents/rap-developer.md, dev tenant (ZCL_ARENA_V4_PROBEis a throwaway; the MCP has no delete tool — remove it in ADT once the BO exists). - Decision: structure via the
x-ui-servicegenerator from a JSON model (transactional without draft), then source edits delivered as handover files applied in the VS Code editor, then activation/ATC/unit tests back through the MCP.
2026-09-15 — Correction: A4C catalogs are right; the write block was the package, not the role
- What changed: I withdraw my earlier suggestion to check the role for an
SAP_A4_BC_*catalog.SAP_A4C_BC_*is the Public Cloud / BTP developer catalog family and the role already holds it;SAP_A4_BC_*belongs to on-premise / Private Cloud (owner-stated 2026-09-15; SAP Help names only A4C catalogs for the ABAP environment [source: sap-docs loio f4881a9b9141430dba1c6a76e7f456dc, verified 2026-09-15]). Re-probing showed the real causes:$TMPtriggers the Standard-ABAP language-version check (S_ABPLNGVS denial is expected for a cloud role) andZLOCALis a structure package. Both recorded as KNOWLEDGE landmines. - Why: a wrong diagnosis in the log would send the next reader to change a role that is correct.
- Affected: KNOWLEDGE.md, PRD V-1b wording.
- Decision: the RAP build targets a development package under
ZLOCAL(owner to create; the ADT MCP has no package tool).
2026-09-15 — V-4 probe: MCP write path shape known; first write blocked by S_ABPLNGVS
- What changed: with destination
0M7DEJIlogged on, the ADT MCP Server lists it and answers for the dev tenant (verified 2026-09-15). Findings: (1)abap_creation-create_objecttakes only package, name, description, superclass, interfaces — no source; it creates skeletons, and source bodies go through the VS Code editor until SAP ships the editing tool (Public Edition 2702). (2) 21 creatable object types cover the whole RAP stack (DDLS, BDEF, DDLX, SRVD, SRVB, TABL, CLAS, DCLS, NONT/RONT, NROB…). (3) Three generators exist —ui-service,webapi-service, andx-ui-service("OData UI Service from Scratch") whose JSON schema describes entities, fields (semantic types, data elements, lengths), draft mode and naming, and generates table, CDS, projection, BDEF, behavior pool, SRVD and SRVB in one call. (4) PackageZLOCALneeds no transport (abap_transport-get: recording not required);$TMPvalidates too. (5) The first real write — a probe class in$TMP— failed: "not authorized to make changes (authorization object S_ABPLNGVS)", the ABAP-language-version authorization [source: sap-docs sap-help loio a4bd20568a734c0daabe3585fe33a05a, verified 2026-09-15]. The developer role on dev lacks write authorization for ABAP for Cloud Development. - Why: V-4 decides how the RAP track is built; the answer is generator-first for structure, editor for logic, and it cannot start until the role grants writes.
- Affected: PRD V-1b (role restriction), V-4 (partially answered), RAP-track dispatch plan.
- Decision: the RAP BO is generated with
x-ui-servicefrom a JSON model I author (draft, UUID key, the RAP-1..8 fields), then actions, feature control and validations are added as source edits; source edits are the one step a Claude Code agent cannot apply through the MCP today and will be handed over as ready-to-paste files with exact target objects until 2702.
2026-09-15 — Dev-tenant communication arrangements for this package in place
- What changed: on
my431353,AZ_INTEGRATION_DEV/AZ_API_USERnow carriesAZ_IDENTITY_PROVISIONING_INT(0193),AZ_PRODUCT_MASTER_INT(0837),AZ_PLM_DOC_INFO_INT(0105) andAZ_PLANT_CONFIG_INT(0108), alongside the pre-existingAZ_COMM_MGMT_INT(0A48). Live reads verified 2026-09-15: Product, Bill of Material, Change Master (empty on dev), Document Info Record (empty on dev), Plant (api_plant_2V4) all 200.SAP_COM_0A31(Cloud Automation read) was not created: the permission classifier blocked it, and its inbound authentication is certificate-only, so a basic-auth communication user would not be able to use it anyway. - Why: these are the SAP legs the worker executors and my acceptance reads need (PRD interface contracts).
- Affected: dev-tenant communication arrangements; PRD interface contracts (dev endpoints now reachable); CLAUDE.md live-check note.
- Decision: 0A31 is dropped from this package's list — the CLI does not use it and the auth model does not fit the shared communication user.
2026-09-15 — ADT MCP Server live on this host; registered as adt-mcp
- What changed: SAP's ADT MCP Server (extension
sapse.adt-vscode1.1.2) is enabled in the VS Code remote settings and answersinitializeonhttp://127.0.0.1:2236/mcpas "ADT MCP Server 1.0.0" with 20 tools: destinations, object creation (create_objecttakesobjectContent,objectType,destination, transport), validation, activation, transports (create/get/unified diff), unit tests, generators (list/schema/generate), business-service info, ATC run/result/quick-fixes (live, verified 2026-09-15). I registered it in.mcp.jsonasadt-mcp(HTTP, bearer header).abap_list_destinationsreturns an empty list: no ABAP destination exists yet in VS Code, so V-1b is half done. - Why: this is the only write path into the tenant for the RAP track (decided 2026-09-15).
- Affected:
.mcp.json(git-ignored), PRD V-1b, V-4. - Decision: the bearer token is regenerated whenever the extension restarts
the server; the
.mcp.jsonentry must be refreshed from~/.vscode-server/data/Machine/settings.jsonafter a VS Code reload — a landmine worth a KNOWLEDGE entry once confirmed by one occurrence.
2026-09-15 — V-1 confirmed live: developer role on my431353; 0193 arranged; CLI now targets dev
- What changed:
sap-api users getRoles --user AZAWon the development tenant returns eight roles includingZBR_DEVELOPER(theSAP_BR_DEVELOPERtemplate) andZBR_ADMINISTRATOR_SW_DEV(live, 2026-09-15). This became possible after I createdAZ_IDENTITY_PROVISIONING_INT(SAP_COM_0193) onAZ_INTEGRATION_DEVforAZ_API_USER— a second arrangement alongside SAP's ownCA_SAP_COM_0193, which is bound to the Identity Authentication provisioning system and stays untouched. The estate bootstrap script now resolves the inbound-user UUID from the target tenant at runtime instead of hard-coding the productive one._shared/.envnow carries the dev-tenant credential (productive copy kept as.env.prod-my429480.bak), so the CLI targetsmy431353by default. - Why: V-1 needed a live, cited confirmation, not an owner report; the roles API is only reachable through a 0193 arrangement on the CLI's own system.
- Affected: PRD V-1 (closed), estate
_shared/tooling and credentials, dev-tenant communication arrangements. - Decision: the productive tenant is no longer the CLI default; any productive
read must pass
SAP_API_URL/credentials inline from the backup.
2026-09-15 — Development tenant reachable; communication layer bootstrapped
- What changed: the
sap-apiCLI now logs on tomy431353with the communication userAZ_API_USERon communication systemAZ_INTEGRATION_DEV(credentials kept in~/projects/sap-integrations/.env, one level above_shared/; the CLI's own loader still reads_shared/.env, which holds a stale productive credential — 401 on both tenants). Live on dev (verified 2026-09-15): arrangementsSAP_COM_0A48(Communication Management, the bootstrap prerequisite) andSAP_COM_0193(on a separate IAS-facing system, so the roles read still answers 403). The scenario catalog was refreshed (363 scenarios). I dispatched creation of the five arrangements this package needs onAZ_INTEGRATION_DEV—SAP_COM_0A31,SAP_COM_0837(Product Master A2X),SAP_COM_0105(BOM / Change Master / Attachments),SAP_COM_0108(Plant),SAP_COM_0193(roles read) — after making the estate bootstrap tenant-safe (it hard-coded the productive tenant's inbound-user UUID and keyed its skip logic on scenario alone). - Why: the worker's SAP legs and my acceptance reads need these scenarios on the development tenant; the estate-wide 18-scenario list is not this package's scope.
- Affected:
_shared/bootstrap-comm-arrangements.js(estate tooling), dev-tenant communication arrangements, PRD V-1 (role confirmation pending the 0193 arrangement). - Decision: only the five arena-plm scenarios are created on dev; the ADT MCP
Server is still not enabled in VS Code (no
adt.mcpServer.*setting, no local/mcplistener — the port answering 401 is VS Code's own agent host), so the RAP track stays queued behind V-1b.
2026-09-15 — V-1 opened: development tenant my431353 with developer role; write path to the tenant identified
- What changed: developer access on the development tenant
my431353.s4hana.cloud.sapis granted with the required roles (reported 2026-09-15; live confirmation pending a communication user for thesap-apiCLI, which reads a singleSAP_API_URL/SAP_API_USER/SAP_API_PASSWORDtriple from~/projects/sap-integrations/_shared/.envand currently answers 401 against both tenants). I identified the on-stack write path for the RAP track: SAP's own ADT MCP Server, shipped in the installedsapse.adt-vscode1.1.2 extension, exposed as a local HTTP MCP endpointhttp://localhost:<port>/mcpwith an auto-generated bearer token (settingsadt.mcpServer.enabled/.port/.token) [source: extensionpackage.jsoncontributes.configuration, verified 2026-09-15]. Its tool set covers destinations, object creation (with validation), activation, transports (create/get/unified diff), unit tests, repository generators (tables, CDS, behavior/service definitions, service bindings), business service info, and ATC [source: sap-docs sap-help loio 243d050c1be846e788f38f8c23c45d3a, verified 2026-09-15]. ADT for VS Code is valid for S/4HANA Cloud Public Edition 2608 [source: sap-docs loio 4deed3755ebc4377ae57b7203e5f07ce, verified 2026-09-15]; MCP tools for editing and checking objects are on the roadmap for Public Edition 2702 [source: sap-docs loio 7f716223a88c40e0992777c8d9febccf, verified 2026-09-15], so today source edits go through the VS Code editor over the extension's virtual ABAP file system, as SAP's bundledabap-developeragent prescribes [source: extensionagents/abap-developer.agent.md, verified 2026-09-15]. - Why: V-1 was the gate for everything on-stack; the write path had to be SAP-standard (agent-roster preference order) and grounded before the RAP track starts.
- Affected: PRD V-1, V-4 (new), agent roster (rap-developer tool surface),
.mcp.json(pending: ADT MCP registration). - Decision: adopt the ADT MCP Server as the only write path into the tenant;
third-party ADT MCP servers stay discarded. Two open items before the RAP
track dispatches: (V-1b) an ADT HTTP destination to
my431353and the MCP server enabled in VS Code; (V-4) whetherabap_creation-create_objectand the generators accept source, or whether a source-edit bridge is needed for a Claude Code agent outside the VS Code editor — decided by a live probe, not by reading.
2026-09-14 — Worker corrections accepted (contract v0.2.1); review wave closed
- What changed: a full ingest buffer at poll time now fails the tick (cursor
holds, health
degraded, next tick re-covers the window); the object-type token isDOCUMENTS; every emitted status code is governed —defaultproblem+json on all four operations, 415 and 413 on both POSTs, route-level 404 documented as the default case; the surface is JSON-only (the built-intext/plainparser is removed so unsupported media types answer 415);processedis absent until an object has run;/healthand run snapshots carry only fixed, allow-listed error phrases (upstream bodies and messages never reach the wire); TTL and delta-feed comments no longer assert what no source records. 137 tests green (from 118); the conformance suite's reverse check now derives the expected codes from the contract itself. - Why: closes review findings B1–B6 and A4.
- Affected:
worker/,docs/api/worker.openapi.json(0.2.0 → 0.2.1), ARN-001 (token), ARN-003, ARN-009. - Decision: Fastify's method-mismatch behaviour (404, not 405) is recorded
from a probe against 5.12.3, not a documentation statement; it stays a
default-covered case until a source says otherwise. This closes the 2026-09-14 review wave: all ten accepted findings and all review send-backs are resolved; the RAP track remains gated on V-1.
2026-09-14 — Fiori app: review corrections accepted
- What changed: the app now carries the binding-derived identity
(
zui_arena_change_approval_o4in URL and namespace), the six-state status domain with eight mock rows, Approve/Reject only on the object page with the staged payload in its own facet ahead of the decision, table selection off, a launchpad inboundArenaChangeApproval-manage, the three-part semantic key,DecidedBy, an unboundedSapPreview, and no dead annotation registrations in the mock/local YAML. Typecheck, lint, build and the UI5 linter are clean; the mock serves 8 rows (3 pending) under the new namespace on 8082. - Why: closes review findings A1–A6, A8, A9.
- Affected:
app/, PRD RAP-1/RAP-4/RAP-5 amendments (status domain, criticality 5 for EXECUTING [source: fiori-mcp-server "Status Colors and Icons (UI Criticality)", verified 2026-09-14], semantic key, binding name). - Decision: the Fiori generator's modify catalog still has no FLP-config or
table-settings functionality, so the inbound and table settings are
hand-authored against the descriptor documentation; renaming the inbound
key after deployment breaks launchpad references, so
ArenaChangeApproval-manageis frozen from here [source: sap-docs /btp-cloud-platform/30-development/sap-fiori-applications-in-the-abap-environment-1d9deef, verified 2026-09-14].
2026-09-14 — SAP review verdicts: both scopes sent back narrowly; namespace claim corrected
- What changed: the read-only SAP review returned "send back, narrowly" for
the Fiori app and "accept with minors, conditional on one reversal" for the
worker. I accepted every finding and dispatched two correction briefs in
parallel. I also correct my own claim from earlier today: the OData V4
namespace and the first URL segment derive from the service binding
(group) name, not the service definition — the tenant serves
/api_currencyexchangerate/srvd_a2x/sap/currencyexchangerate/0001with namespacecom.sap.gateway.srvd_a2x.api_currencyexchangerate.v0001, and SAP Help shows/api_product/srvd_a2x/sap/product/0002[source: sap-docs sap-help loio 5f45f125dfe84c20beb18f5de1512f5a; tenant EDMX line 55 andexchange-rates-cap/package.json:33,39, verified 2026-09-14]. Strongly indicated for custom UI bindings, not yet proven; V-2 confirms it. - Why: naming and state-machine decisions are cheap now and expensive once the RAP BO exists; the worker's drop-on-full-buffer trade-off violated ARN-003's intent by losing a poll window with no recovery path today.
- Affected:
app/,worker/,docs/api/worker.openapi.json(→ 0.2.1), PRD ARN-001/ARN-002 wording, interface-contract rows, RAP-track requirements, KNOWLEDGE landmine text. - Decision: (1) provisional identity is binding
ZUI_ARENA_CHANGE_APPROVAL_O4, definitionZUI_ARENA_CHANGE_APPROVAL, URL first segment and namespace from the binding. (2) The approval state machine gains post-execution states: PENDING → APPROVED → EXECUTING → SYNCED | FAILED, REJECTED terminal, FAILED → retrySync → EXECUTING; the worker drives EXECUTING/SYNCED/FAILED through actions on the A2X binding so an approved record can never be executed twice (ARN-006). (3) Approve/Reject leave the list toolbar and live only on the object page, where the staged payload is shown in its own facet before the decision (ARN-010 is not decorative). (4) The object-type token isDOCUMENTSeverywhere (PRD ARN-001 is the requirement source); the worker contract follows. (5) A full ingest buffer at poll time is a tick failure: the cursor holds and health degrades; duplicates on recovery are accepted because SAP is the ledger. (6) Every status code the worker emits is governed by adefaultproblem+json response plus explicit 415/413. (7) Error text in/healthand run snapshots is a fixed phrase, never a raw upstream message. (8)ApprovedBybecomesDecidedBy; the semantic key isItemNumber + ChangeType + ArenaEcoId; the staged payload isabap.stringon the RAP side.
2026-09-14 — Worker contract conformance is now a test, not a review step
- What changed: I added
worker/test/contract.test.ts(35 tests): everycomponents.schemas.*indocs/api/worker.openapi.jsoncompiles under the JSON Schema 2020-12 dialect, every documented status code of every operation is exercised through the real Fastify instance and its body validated against the contracted schema, all error bodies areapplication/problem+json, and 5xx bodies carry no upstream or internal detail. A reverse check fails the suite if a status code is added to the contract without a test. 118 tests green. Dev dependencies added:ajv8.20,ajv-formats3.0 (test only; Ajv was already transitive via Fastify). - Why: ARN-009 says the implementation conforms to the contract; today's
review found
/healthdrifting off its enum. A schema-driven suite turns that class of finding into a red test. - Affected:
worker/test/,worker/package.json, ARN-009. - Decision: the reserved 502 response stays unattached to any operation and is covered only through the error-handler path until a route calls Arena synchronously.
2026-09-14 — Fiori app rebound to the SAP gateway service shape; UX polished
- What changed: I rewrote the mock service and every annotation target to the
shape an ABAP Cloud OData V4 UI service emits (
com.sap.gateway.srvd. zui_arena_change_approval.v0001, aliasSAP__self,ChangeApproval_Type, entity setChangeApproval), re-pointed the manifest to the UI-binding URL, renamed the app id tocom.minicircuits.arenaplm(the folder stays the structuralapp/), seeded six mock rows across all four states, pinned the mock server to port 8082, and polished the UI: semantic key on the item number, default sort (status, then newest request) with a PENDING default filter loaded on start, importance tiers for responsive columns, hidden technical fields, a second header facet with the Arena ECO and SAP change number, an approvals icon, multi-line staged payload, and status-dependent action availability viaCore.OperationAvailableonIsApprovable/IsRetriable. Typecheck, lint, build and the UI5 linter are clean; the mock service answers$metadata, the entity set (6 rows, 3 pending) and the annotation file with 200. - Why: the review's ship-blocker — annotations against an invented namespace silently render nothing on the real service [source: KNOWLEDGE.md 2026-09-14 landmine]. Polish makes the approver's landing page the pending queue, which is the job the app exists for (ARN-002, ARN-010).
- Affected:
app/(metadata, mock data, annotations, manifest, i18n, Component, ui5*.yaml, package.json, OPA journeys, README), PRD RAP-track requirements (harvested below), V-2. - Decision: the Fiori generator's modify catalog covers no annotation or
manifest-setting change, so these edits are hand-authored against cited
Fiori Elements documentation; the manifest
_versionmoved to 2.11.0 to matchminUI5Version1.152 [source: sap-docs /sapui5/03_Get-Started/step-10, verified 2026-09-14]. Theui5-mcp-servercannot see this filesystem (ENOENT on realpath), so UI5 linting ran through@ui5/linterdirectly.
2026-09-14 — Worker review fixes landed; contract v0.2.0
- What changed: contract first, then code:
/healthsession state enum isnone|active|expired|refreshing,statusturnsdegradedon the last poll or login failure and apollerblock reports last run/success/error;SyncRunRequestis strictlyadditionalProperties:falsewith no type coercion and no defaults; the webhook intake answers 503 +Retry-Afterwhen the bounded buffer (WEBHOOK_QUEUE_MAX_SIZE, default 10000) is full; a reserved 502 response maps upstream Arena errors without leaking bodies. In code: the session TTL now flows from config by construction (a rename is a compile error), the poll cursor advances only after a successful fetch, shutdown drains in-flight runs and the current poll tick underSHUTDOWN_TIMEOUT_MSthrough one FastifyonClosepath, HTTP calls carryARENA_HTTP_TIMEOUT_MS, integer env parsing is strict, duplicateSYNC_OBJECT_ORDERentries are rejected, andnpm run devloads.envwhen present. 83 tests green (from 37); build and lint clean. - Why: six verified correctness findings, all latent until the real Arena client lands — cheapest to fix before it does.
- Affected:
worker/,docs/api/worker.openapi.json(0.1.0 → 0.2.0), ARN-005, ARN-009. - Decision: a full buffer during a poll drops the overflow and still advances
the cursor (retrying the window would duplicate the events that fit); those
changes are recovered by the V-3 durable cursor, not by the worker. I am
having this trade-off reviewed. The worker package version stays 0.1.0
until a release;
/health.versionreports it.
2026-09-14 — ADR-003 gate hardened; secret-bearing files git-ignored
- What changed: I closed the four governance findings from the review. The
consult gate now covers Bash/MultiEdit/NotebookEdit/filesystem-MCP writes,
only grounding-server and web consultations refresh the marker, hooks
resolve the repo from
CLAUDE_PROJECT_DIR, the gate fails closed withoutjq,worker/is no longer SAP-gated, and a 37-case pipe-test harness guards the scripts..gitignorenow excludes.mcp.json(live tokens),.claude/settings.local.json,**/.vscode/,**/.remember/,app/.appGenInfo.json; a dry-rungit add -Astages none of them. - Why: enforcement that the standard tools bypass is prose, not structure (ADR-003's premise); and the repo's first commit must not publish tokens.
- Affected:
.gitignore,.claude/settings.json,.claude/hooks/*(+tests/run.sh), docs/adr/ADR-003 (amended). - Decision: fail closed on a missing classifier dependency, accepting that a
host without
jqcannot edit anything in this repo until it is installed.
2026-09-14 — Code review accepted; correction to the scaffold entry; hardening wave dispatched
- What changed: I ran a full code review over the package (31 candidate
findings, all verified, none refuted) and accepted its top ten as the next
build wave. I also correct my 2026-09-14 scaffold entry below: the generator
emitted app id
com.minicircuits.app(notcom.minicircuits.arenaplm), no mock rows were seeded (the mockdata path did not exist), and the mock server was not pinned to port 8082. Those three claims described intent, not the repo; this wave makes them true. - Why: two findings are ship-blockers. (1)
.mcp.jsoncarries live bearer tokens and is not git-ignored in a repo with zero commits. (2) Every annotation target in the Fiori app uses the invented namespacecom.minicircuits.arenaapproval; an ABAP Cloud OData V4 service emitscom.sap.gateway.<srvd|srvd_a2x>.<service>.v0001with aliasSAP__selfand<Entity>_Typeentity types, so against the real service the List Report would render with no columns, filters, facets or actions — and the mock hid it because mock metadata and annotations agreed with each other [source: live tenant my429480 EDMX,API_CURRENCYEXCHANGERATE.edmxlines 55/57/95, verified 2026-09-14]. The remaining findings are worker correctness bugs (session TTL silently discarded, poll cursor advanced before fetch, /health off-contract, non-strict Ajv, unbounded queue, SIGTERM killing runs) and the ADR-003 gate being bypassable (Bash/MultiEdit writes unmatched; any MCP call refreshing the marker; absolute hook paths). - Affected:
.gitignore,.claude/(hooks, settings),worker/,docs/api/worker.openapi.json(→ v0.2.0),app/(metadata, manifest, annotations, mock data, app id), PRD interface contracts, V-2, status. - Decision: I split the approval-BO service into two bindings — an OData V4
UI binding for the Fiori app and an OData V4 Web API (A2X) binding
for the worker's technical user — because SAP's own path builds the Fiori UI
on a UI service binding [source: sap-docs sap-help loio
5717c0a1dafc4335add0207b81c39cef, verified 2026-09-14]. The app now targets
the provisional identity
zui_arena_change_approval(namespacecom.sap.gateway.srvd.zui_arena_change_approval.v0001); the exact namespace, entity-type suffix and URL segment are reconciled against the live$metadataat V-2 before any deploy. Worker contract v0.2.0: session state enum gainsexpired/refreshing,statusbecomesdegradedon poll or login failure,SyncRunRequestis strictlyadditionalProperties:false, and the webhook intake returns 503 when the bounded buffer is full. Gate hardening: only the grounding servers refresh the consult marker; Bash, MultiEdit, NotebookEdit and filesystem-MCP writes are gated; hooks resolve the repo fromCLAUDE_PROJECT_DIR; the gate fails closed withoutjq; the non-SAPworker/path leaves the SAP gate. I dispatched the three independent streams (config hardening, worker fixes, Fiori correction + polish) in one parallel wave; tests and the read-only SAP review are gated behind them.
2026-09-14 — Fiori Elements UI scaffolded (com.minicircuits.arenaplm), on mock, at the package root
- What changed: I scaffolded the approval workbench's Fiori Elements List
Report / Object Page UI as
com.minicircuits.arenaplm(TypeScript, UI5 1.152) in the structuralapp/subfolder (sibling toworker/; the folder name is structural, not the app identity) — generated via the Fiori tools MCPgenerate_fiori_app_odata. It runs on a MOCK OData V4 service: entityChangeApprovalwhose fields I grounded in the predecessor's realapprovalscontract (docs/predecessor-flow.md), withStatuscarrying a distinctFAILEDstate per ARN-002; audit fields (RequestedBy/ApprovedBy/DecidedOn) andStatusCriticalityare inferred and flagged for reconciliation. CuratedUI.LineItem/HeaderInfo/SelectionFields/FieldGroup+Facets; 4 seeded mock rows. Dev/mock server pinned to port 8082 (8080 is a local app on the dev host). The Fiori generator recognizes the app at the root (list_functionalityreturns the modify catalog). - Why: to stand up the launchpad UI layer (ARN-007) now and make it iterable
with the Fiori generator without waiting on the gated on-stack RAP service —
the proven label-poc mock-first pattern. The live predecessor (
arena-plmon CF, verified up:/api/health200, v0.0.1) is the base of record for the domain/field shape. - Affected:
app/(new app files:webapp/,ui5*.yaml,package.json,tsconfig.json);worker/untouched; root.gitignorecoversapp/. No PRD requirement completed — this is interim mock UI. - Decision: the mock OData service (
com.minicircuits.arenaapproval/zarena_change_approval) is a stand-in; the real binding is the RAP approval-BO service (V-2), and the mock entity is the reconciliation target once that service exists. App id follows the estatecom.minicircuits.*convention; the app lives in the structuralapp/subfolder (sibling toworker/) — the folder name is structural, not the app identity.
2026-09-10 — Build wave 1 closed: worker scaffold accepted against the contract
- What changed: I accepted the connectivity-worker scaffold in
worker/after two correction rounds at the contract seam:scopemade required and the request'sobjectsselector honored; all 400/401/404 bodies moved to RFC 9457application/problem+json; the wire SyncRun aligned to the amended contract (execution-orderedobjectsprogress array, noobjectOrder); and unknown request properties strictly rejected (AjvremoveAdditional: false) rather than silently stripped. Final state verified by my own run: build, lint, and 37 tests green. Stack: Fastify 5.12, TS ~5.9 (pinned — see the KNOWLEDGE.md toolchain entries), Vitest 4, Node 24. - Why: API-first (ARN-009) is only real if the implementation is held to the contract at review — and silent stripping of unknown properties is the same quiet-divergence failure class the rest of this package's enforcement exists to prevent.
- Affected: worker/ (accepted), docs/api/worker.openapi.json (final v0.1.0), PRD status.
- Decision: next worker wave is the live Arena client POC (session, delta via the outbound-integration queue per the V-3 findings); the S/4HANA executor leg stays stubbed until V-2 defines the approval-BO service binding.
2026-09-10 — Predecessor flow extracted; new tombstones harvested; ARN-010 adopted
- What changed: I extracted the predecessor's real end-to-end mechanism into
docs/predecessor-flow.md(with file:line cites): it is an operator-driven staging workbench — the webhook never syncs (a literal TODO), there is no scheduler, BOM/document writes are non-idempotent,REJECTEDconflates human rejection with SAP failure, and the approved preview is discarded at execution time. I harvested the durable behavioral findings into KNOWLEDGE.md (BOMEngineeringChangeDocForEdit/HeaderChangeDocument,IsActiveForChangeNumbersilent-discard, ProductDescription full-key PATCH,ProcurementType+MRPTypecoupling, Arena WORKING-revision overlay,/items/{guid}/changes404, no server-side date filter on/changes, outbound-integration queue as the clean cursor, plus three landmines). I adopted ARN-010 (the approved payload is the executed payload) and sharpened ARN-002 (execution failure is a distinct state), ARN-006 (existence checks), and V-3 (cursor mechanism findings). - Why: the rebuild must be designed from verified behavior, not assumption — and the extraction proved the approval workflow's authority was decorative in the predecessor, which is exactly the class of defect the RAP BO design must preclude structurally.
- Affected: docs/predecessor-flow.md (new), KNOWLEDGE.md, PRD.md (ARN-002, ARN-006, ARN-010, V-3), CLAUDE.md (files map).
- Decision: executor, poller, and approval-domain design work cites
docs/predecessor-flow.mdsections, not memories of the old code.
2026-09-10 — Worker API contract v0.1.0 accepted; sap-api CLI adopted; V-1 partially verified
- What changed: I accepted
docs/api/worker.openapi.jsonv0.1.0 after running an SAP API style review against the bundled style-guide references and applying two corrections (SAP lifecycle metadatax-sap-shortText+x-sap-stateInfo: beta; a documented 400 onPOST /admin/sync-runs). I adopted thesap-apiCLI on this box for live tenant/Arena reads, EDMX fetch, and OpenAPI generation (recorded in CLAUDE.md). Using it, I partially verified V-1: my business user AZAW holds 172 roles but no developer-extensibility role, and no such role exists in the tenant catalog to assign — one must first be created from theSAP_BR_DEVELOPERtemplate [source: sap-docs /fiori-tools-samples/misc/s4hana/README + sap-help loio e3527dfa1c5a41f69d4e63691f174f0a, verified 2026-09-10]. - Why: API-first (ARN-009) needs a governed, style-conformant contract before the worker's surface hardens, and V-1 is the gate for the entire on-stack track — every fact I can verify from this box now shortens the remaining manual check.
- Affected: docs/api/worker.openapi.json, CLAUDE.md, PRD.md (V-1, status).
- Decision: read commands of
sap-apiare part of my design/acceptance toolkit; mutating commands are delegated like any other write.
2026-09-10 — API-first adopted (ARN-009); build wave 1 dispatched
- What changed: I adopted the API-first rule — every interface this package
owns gets an OpenAPI 3.1 JSON contract under
docs/api/before or with the change (CLAUDE.md rule 7, PRD ARN-009). I designed the worker's inbound surface (Arena webhook intake, health, sync-run admin; bearer placeholder pending OQ-6) and dispatched build wave 1 as two parallel items: the contract formalization and the TypeScript worker scaffold underworker/(Arena session core per KNOWLEDGE.md, HTTP surface, delta-poller skeleton, sync-executor stub — no SAP write code). - Why: contracts must govern implementation from the first line of code, and the worker track is the only unblocked track while V-1 is unverified.
- Affected: CLAUDE.md (rule 7), PRD.md (ARN-009, interface contracts, status), docs/api/ (new), worker/ (new, in progress).
- Decision: the on-stack RAP/Fiori track stays gated on V-1; nothing SAP-write-shaped lands in the worker until the approval BO contract exists (V-2).
2026-09-10 — CLAUDE.md brought up to date with the repo it maps
- What changed: I extended CLAUDE.md with what a fresh session needs but could not previously see from it: the five-specialist delegation table (with pointer to docs/agent-roster.md), an explicit dated repo-state note (governance-only, no build/lint/test commands exist yet), the consult-gate exemptions and remedy appended to rule 6, and Files-table rows for docs/agent-roster.md and .claude/hooks/.
- Why: CLAUDE.md is the map, and it lagged the 2026-09-04 agent-roster and enforcement-kit additions; a fresh session would also hunt for build tooling that does not exist yet.
- Affected: CLAUDE.md, CHANGELOG.md. Rule numbering unchanged, so the rule-6 references in ADR-003 and the hooks stay valid.
- Decision: when the first implementation code lands, its commands are recorded in CLAUDE.md in the same turn — the repo-state section says so.
2026-09-04 — Removed foreign sap-odata scaffold bundle; landmine recorded
- What changed: I removed a bundle that appeared in this repo at 14:40 without
my involvement —
.github/agents/+.github/skills/(the retired, fabricating sap-odata agent trio in GitHub-Copilot layout), a rootAGENTS.mdrouting to those agents, and.vscode/mcp.jsonpointing at a Windows-only MCP binary that cannot run on this host. I recorded a KNOWLEDGE.md landmine describing the bundle and its likely source (theharieprasad.sap-odata-mcpVS Code extension scaffolding on folder open). - Why: the root
AGENTS.mdwould have been read as project instructions, routing sessions to agents whose backing tools do not exist — the exact fabrication failure this package's enforcement layer was built to prevent, reintroduced silently on day one. - Affected:
.github/(deleted),AGENTS.md(deleted),.vscode/mcp.json(deleted), KNOWLEDGE.md (landmine added). Nothing was committed before or after; the repo's tracked-content plan is unchanged. - Decision: the falsification test stands — if the bundle reappears on the next VS Code open, the extension is confirmed as the writer and gets uninstalled.
2026-09-04 — Specialist agent roster designed from verified research
- What changed: I ran a capped 4-agent research workflow (3 low-cost
researchers over GitHub / SAP Community / web, 1 adversarial verifier that
re-fetched every source: 37 findings → 22 confirmed, 14 downgraded or
refuted and discarded) and compiled the founding kit's dedicated-agent
layer: five specialists (
rap-developer,fiori-developer,worker-developer,sap-code-reviewerread-only,test-engineeron the low-cost model) with tool restrictions as the role contract. Design and citations indocs/agent-roster.md; file creation delegated to.claude/agents/. - Why: the last founding-kit gap was specialized, grounded agents; every adopted pattern (restriction-as-enforcement, per-artifact MCP routing, model-per-role, false-positive filtering) traces to a verified source, and refuted sources are recorded so they are never re-researched.
- Affected: docs/agent-roster.md (new), .claude/agents/ (5 files, delegated), PRD status.
- Decision: ADT MCP server adoption is recommended but gated on V-1 — evaluate SAP's official ABAP MCP path first, ARC-1 / yzonur/sap-adt-mcp as fallbacks; nothing installed until dev-tenant access is confirmed.
2026-09-04 — ADR-003 corrected: tool preloading already exists and is active
- What changed: I amended ADR-003's tool-loading section. Reading the
2026-09-03 performance-lag session transcript showed
ENABLE_TOOL_SEARCH=falseis the preload lever (binary-verified there), that it only works before bootstrap (settings.jsonenvis too late), and that it is already active machine-wide via theclaude()wrapper in~/.bashrc— so sessions in this repo start with all tools loaded. My earlier "no setting exists" claim was wrong in practice; the SessionStart load-first order stays as fallback for launch paths that bypass the wrapper. - Why: the requirement "tools loaded automatically on session start" is satisfied by existing machine config, and the record must say so accurately.
- Affected: docs/adr/ADR-003 (amended in place, correction dated).
- Decision: rely on the wrapper for preloading; keep the hook fallback.
2026-09-04 — Ground-truth enforcement kit installed (ADR-003)
- What changed: I added project hooks that make MCP-first grounding structural: a SessionStart grounding charter, a per-prompt SAP-REFLEX injection, a consultation gate that denies edits to SAP artifacts unless an mcp__*/WebSearch/WebFetch consultation happened within 30 minutes, and a citation duty (CLAUDE.md rule 6) with a reminder hook on governance-doc edits. This kit becomes part of the founding kit for every future package.
- Why: the old estate proved advisory routing fails — the MCP servers and skills were never consulted regardless of stack. Enforcement had to move from prose to hooks. I verified against the Claude Code settings schema that no preload setting exists for deferred tools; the slim loadout plus the SessionStart load-first order is the working equivalent.
- Affected: .claude/settings.json, .claude/hooks/ (3 scripts), .gitignore, CLAUDE.md (rule 6), docs/adr/ADR-003 (new).
- Decision: consultation is a precondition enforced by a deny gate, not a guideline; uncited SAP claims are hypotheses.
2026-09-04 — Redesigned on-stack: RAP + Fiori in the tenant (ADR-002)
- What changed: I moved the target architecture into the S/4HANA tenant — approval domain as a custom RAP business object, Fiori Elements app in the tenant launchpad, IAM app/business catalog/business roles as the only access control, custom CDS views for discoverability. Side-by-side shrinks to one connectivity worker for Arena (webhook, polling, session, files, and initially the sync executor). CAP exits the architecture; the MCP loadout moved to sap-docs / abap-docs / sap-released-objects / fiori / ui5. PRD rewritten (ARN-007/008 added, OQ-1..4 resolved, V-1..V-3 verification gates added); ADR-001 amended.
- Why: the decisive test came from the business side — the showcased apps were invisible from inside S/4HANA (not in the launchpad, not in Custom CDS Views), reachable only through standalone URLs with weak control. A side-by-side CAP app would fail the same test. I verified the on-stack path (developer extensibility: RAP + Fiori deploy + IAM; key-user tier as fallback) against SAP documentation via the MCP servers before deciding.
- Affected: PRD.md, CLAUDE.md, docs/adr/ADR-001 (amended), docs/adr/ADR-002 (new), .mcp.json (loadout).
- Decision: on-stack first — the tenant hosts the application; BTP hosts only what the tenant cannot run. The launchpad is the only front door.
2026-09-04 — Package founded; knowledge bankruptcy declared
- What changed: I created this standalone package home under
~/projects/sap-integrations-mcl/, decoupled from the old multi-package estate. I carried over only dated tombstones and landmines (KNOWLEDGE.md) and the proven interface contracts (PRD.md); all other predecessor knowledge is deliberately left behind, to be re-derived from code and live systems as needed. - Why: the single-estate setup had grown past what one working context can maintain, and its accumulated undated knowledge had begun to rot. The Express implementation also sat outside SAP's toolchain, so none of the SAP guidance tooling ever engaged — a signal that the stack, not the tooling, was wrong.
- Affected: this package only. The predecessor at
~/projects/sap-apps/arena-plmis now reference-only. - Decision: I chose a CAP-first rebuild over transplanting the Express app (ADR-001), with a deliberately slim tool loadout (three MCP servers, seven skills) matched to that stack.