Sync current sources: clean RAP handover names, app rebind, tooling

Working-tree state as of 2026-09-29, uncommitted since the initial
"upload current sources" commit:

- docs/handover/rap/: renamed the 11 generator-suffixed sources
  (zz*000) to the clean object names built on the tenant, plus the
  A2X leg and parameter-entity edits.
- app/: manifest, annotations, i18n, mock data and local/mock ui5
  configs updated to the live service shape.
- PRD.md, CHANGELOG.md, KNOWLEDGE.md: build record through
  2026-09-19, including the rejected reentrance-ticket path.
- tools/adt-reentrance-login/: retained login helper (new).
- docs/v2/zui_arena_change_appr_o4.metadata.xml: captured live
  $metadata (new).
- Dropped a stray 0.3GB-class Eclipse installer that the initial
  commit had tracked under a URL-mangled filename, and the
  machine-specific 0M7DEJI.code-workspace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-29 10:22:52 -07:00
co-authored by Claude Opus 5
parent f8b45ea4a5
commit 468729eb4e
42 changed files with 4597 additions and 1680 deletions
+699
View File
@@ -2,6 +2,705 @@
Append-only decision log for this package.
## 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 the `redirect-url=http://localhost:<port>/adt/redirect`
flow, 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, because `URLSearchParams` turns a
`+` in a ticket into a space and would corrupt it. Then I captured a real
ticket and tested it: `/sap/bc/adt/core/discovery` and 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 without
`sap-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's `sso2` (MYSAPSSO2 cookie) mode.
- Affected: new `tools/adt-reentrance-login/`, `~/.abap-adt-mcp/systems.json`
(switched to `sso2`, then restored to `sso`), 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 `sso2` cannot 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 type `OData V4 - Web API`
(`create_object` returned `.srvb.json`).
- `fetch_services`: service `ZAPI_ARENA_CHANGE_APPROVAL`, version `0001`,
V4, `isPublished: false`, `bindingCategory: "1"`.
- ATC over the five worker objects (worklist
`12ACF6BD93811FE1ACBA776536DD5BD6`): 0 errors and one priority-3
warning, W607 (+BDL 549) on BDEF `ZC_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]
- 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.authorizationCheck` from `#CHECK` to `#MANDATORY` now:
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 in `ZR_CHANGEAPPROVAL` and
`ZC_CHANGEAPPROVAL`).
## 2026-09-16 — Worker leg: A2X projection view and access control active; A2X BDEF created
- What changed: I activated W1 (`ZC_CHANGEAPPROVAL_A2X` projection view)
and W2 (its access control); both answered "Activation successful."
I then created W3, the projection BDEF `ZC_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_A2X` view), W2 (its access control, with
`protectedEntity`) and W4 (service definition
`ZAPI_ARENA_CHANGE_APPROVAL`) empty in `ZARENA_PLM` [source: adt-mcp
create_object on 0M7DEJI, verified 2026-09-16]. I also corrected
`docs/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 type `OData 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.xml` is the live `$metadata`, byte-identical (sha256
`c13e86e1…`, checked).
- Mock rows carry `StatusText`, `LocalLastChangedAt`,
`__OperationControl` and `SAP__Messages`.
- All annotation targets and action strings use namespace
`com.sap.gateway.srvd.zui_arena_change_approval.v0001` and entity type
`ChangeApprovalType`.
A grep for the old identity over `app/` (excluding `node_modules`/`dist`)
returns nothing. Lint, typecheck and `@ui5/linter` are clean. The mock
server answers `$metadata` and `ChangeApproval` with `$filter`, `$count`
and `__OperationControl` selects.
- 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
`OperationAvailable` overrides went away with the mock metadata, and
`annotation.xml` deliberately 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.
## 2026-09-16 — Live `$metadata` captured: backend contract matches the app; identity names differ
- What changed: the published UI service's `$metadata` is captured in
`docs/v2/zui_arena_change_appr_o4.metadata.xml`. It was copied from the
browser on the UI host `my431353.s4hana.cloud.sap`; browser-decoded `&`
characters were re-escaped. The `-api` host refused the same request to a
business user ("blocked by UCON").
- Matches the app: all 17 app properties with identical EDM types
(`Edm.Boolean` flags, `Edm.Byte` criticality, `Edm.DateTimeOffset`
Precision 7), key `ID`, entity set `ChangeApproval`, and the actions
`approve`, `reject(RejectReason)` (non-nullable) and `retrySync`.
- Differs from the mock: namespace
`com.sap.gateway.srvd.zui_arena_change_approval.v0001` (from the service
definition), entity type `ChangeApprovalType`, URL segment
`zui_arena_change_appr_o4`, extra `StatusText` / `LocalLastChangedAt` /
`__OperationControl` / `SAP__Messages`, and backend-driven
`Core.OperationAvailable`.
I dispatched the app reconciliation.
- 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 `$metadata` replaces the mock metadata and becomes the
app's contract. Button enablement comes from the backend's
`__OperationControl` rather than local `IsApprovable`/`IsRetriable`
overrides, 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_O4` is
published. The ADT for VS Code Publish code lens gave no visible
confirmation, so I verified it live: `fetch_services` reports
`isPublished: true`, and `fetch_service_information` returns
`https://my431353-api.s4hana.cloud.sap/sap/opu/odata4/sap/zui_arena_change_appr_o4/srvd/sap/zui_arena_change_approval/0001/?sap-client=080`
with entity set `ChangeApproval` [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_object` returned `.srvb.json`), and activated it.
- ATC over all 14 UI-leg objects: 0 errors, 0 warnings, 43 infos
(worklist `12ACF6BD93811FE1ACB8096AC6763BD6`).
- `fetch_services`: service `ZUI_ARENA_CHANGE_APPROVAL`, version `0001`,
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]
- 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.abdl` URIs.
## 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 definition
`ZUI_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_PATH` set, 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-mcp` rather 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: SAP `adt-mcp` for 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-mcp` connected. `listSystems`
showed exactly one destination, `MY431353` (client 100, SSO), with policy
`readOnly: true` and `allowedPackages: ["ZARENA_PLM"]`. The first SAP call
(`classIncludes` on `ZBP_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-chrome`
and 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-mcp` is registered in the project `.mcp.json`
(git-ignored, mode 600). It runs over stdio as `npx -y
abap-adt-mcp@2.1.0` with `MCP_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 tenant
`my431353`, client 100, SSO, with `policy.readOnly: true` and
`allowedPackages: ["ZARENA_PLM"]`. The six existing project servers are
unchanged, `adt-mcp` included.
- 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 `getObjectSource` of 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-mcp` 2.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-mcp`
configuration 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.json` and to
register `abap-adt-mcp` in 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-only
`getObjectSource` on 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-mcp` 2.1.0 once through `npx` over stdio.
It ran with `MCP_READ_ONLY=1` and a scratchpad systems file listing only
the development tenant, restricted to `ZARENA_PLM`. `initialize` and
`tools/list` answered: 173 tools, including source read/write and
activation. `listSystems` showed 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 `my429480` is 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
view `ZC_CHANGEAPPROVAL`). All answered "Activation successful." The
locally cached class metadata shows the class active with category
`behaviorPool`. I then created wave D empty: U9 projection BDEF
`ZC_CHANGEAPPROVAL` (`.bdef.abdl`), U11 access control
(`.dcls.acds`), U12 metadata extension (`.ddlx.acds`) and U13 service
definition `ZUI_ARENA_CHANGE_APPROVAL` (`.srvd.acds`). `SRVD/SRV` also
offers an optional `referencedObject` create 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.abdl` for 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-rejected` as
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 managed `strict ( 2 )` behavior definition
`ZR_CHANGEAPPROVAL`. Both answered "Activation successful." U6 activated
through its `.bdef.abdl` URI 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
pool `ZBP_R_CHANGEAPPROVAL` (`create_object` returned only the global
`.clas.abap` path, no local-types include), and U8, the UI projection view
`ZC_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.abdl` for U6, U9 and W3, and the
U6 fallback was not needed), KNOWLEDGE.md.
- Decision: now that an empty `ZBP_R_CHANGEAPPROVAL` exists, 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 U5 `ZR_CHANGEAPPROVAL` on `my431353`. Each activation
answered "Activation successful.", and the tool returned no warnings.
- The table activates through its `.tabl.ddic` URI; `.tabl.json` holds
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_object` returned `…/zr_changeapproval.bdef.abdl`), and U10, the
access control `ZR_CHANGEAPPROVAL` (`…/zr_changeapproval.dcls.acds`,
with `protectedEntity`).
- 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.abdl` URI 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 etag` sits in the entity header of both projection BDEFs.
- `retrySync` writes APPROVED, so EXECUTING is written only by
`markExecuting`.
- All six action handlers set `%fail-cause` and `%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 same
`ItemNumber` + `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_CHANGEAPPROVAL` with privileged
access. The view is access-controlled, and a handler `SELECT` on 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 only `cause-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` (fallback `FROM … WITH PRIVILEGED ACCESS`),
`%op-%action-<name>` on MODIFY response rows, and `preserving type` on
the U5 casts.
## 2026-09-16 — Root view U5 final: derived booleans cast as a whole
- What changed: in `zr_changeapproval.ddls.asddls`, `IsApprovable` and
`IsRetriable` are now `cast( case status when … then abap.char'X' else
abap.char' ' end as abap_boolean preserving type )`. The file header
records why: typed `abap.char` literals make the CASE result CHAR(1)
[source: abap-docs /abap-docs-cloud/ABENCDS_TYPED_LITERAL_V2, verified
2026-09-16], and `ABAP_BOOLEAN` is "of data type `CHAR` of length 1"
[source: abap-docs /abap-docs-standard/ABENDATAOBJECTS_TRUE_VALUE_GUIDL,
verified 2026-09-16], so `preserving type` matches 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 `#XBUT` comments, the mock `metadata.xml`
comment) from FAILED → EXECUTING to FAILED → APPROVED. No labels,
annotations, manifest or mock data changed. `npm run lint` and
`npm run ts-typecheck` pass.
- 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 `executeAction` handler 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 remote
`ui5-mcp-server` cannot 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 etag` sat 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.
- 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) `retrySync` goes FAILED → APPROVED, clears `ErrorMessage`, and the
worker re-claims the record through `markExecuting`. The earlier FAILED
→ EXECUTING could not be claimed, because `markExecuting` accepts 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 `checkDuplicate`
validation 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 failed `markSynced` as 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.
## 2026-09-16 — Wave A created: table, parameter entities, root view exist empty
- What changed: I created U1 `ZCHANGEAPPROVAL` (TABL) and U2–U5
`ZD_CHANGEAPPROVAL_REJECTP`, `ZD_CHANGEAPPROVAL_SYNCEDP`,
`ZD_CHANGEAPPROVAL_FAILEDP` and `ZR_CHANGEAPPROVAL` (DDLS) in
`ZARENA_PLM`. They are inactive and have no source. `abap_transport-get`
answered `isRecordingRequired: false`. Each object passed validation and
creation with the handover JSON unchanged. The table's returned URI ends
in `.tabl.ddic`, not the `.tabl.json` that 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_object` returned
(`.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_PLM` exists again under `ZLOCAL`. ADT MCP
validation of `ZCHANGEAPPROVAL` in 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 only `ChangeApproval`. A scripted comparison against
the app's mock `metadata.xml` confirms that the UI projection carries all
17 app properties plus `approve`, `reject` and `retrySync`. The build
splits into a 14-source UI leg and a 4-source worker leg. The
`markSynced`/`markFailed` parameter 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…000` targets 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) and
`ZAPI_ARENA_CHANGE_APPR_A2X` (26). The service definitions keep
`ZUI_ARENA_CHANGE_APPROVAL` and `ZAPI_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 (`StatusCriticality` as INT1,
`abap_boolean` flags, `utclong`, `sysuuid_x16`) stay unverified until
live `$metadata` exists; 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 `my431353` read-only.
`abap_creation-run_validation` answers "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_details` gives 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_PLM` under `ZLOCAL` under the same name, so
every activation URI pattern verified on 2026-09-15 stays valid. All clean
names fit (`ZCHANGEAPPROVAL` 15, `ZUI_ARENA_CHANGE_APPROVAL_O4` 28).
`ZLOCAL` means no transport request on every create while I prototype. It
is not a dead end for production: a package can be reassigned from
`ZLOCAL` to `ZCUSTOM_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_PLM` contents on `my431353` were 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 of `docs/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 set `ChangeApproval`, and actions `approve`, `reject` and
`retrySync` (`app/webapp/manifest.json`, mock `metadata.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 `ZZ` prefix and a
`000` suffix (KNOWLEDGE, 2026-09-15). I create each object through the ADT
MCP under its final name: table `ZCHANGEAPPROVAL`, `ZR_CHANGEAPPROVAL`,
`ZBP_R_CHANGEAPPROVAL`, `ZC_CHANGEAPPROVAL`, SRVD
`ZUI_ARENA_CHANGE_APPROVAL`, SRVB `ZUI_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_PLM` returned 43 objects, not
the 12 my 2026-09-15 handover README lists. The package holds two default
`x-ui-service` generator sets side by side: the `ZZ…000` set
(`ZZCHNGPPROVAL000`, `ZZR_/ZZC_CHANGEAPPROVAL000`, binding
`ZZUI_ARENA_CHANGE_APPRVL000_O4`) and a set without the suffix
(`ZZCHANGEAPPROVAL`, `ZZR_/ZZC_CHANGEAPPROVAL`, binding
`ZZUI_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 in `docs/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 `ZZ` names 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