What the site claims about the framework, checked against the framework — plus a sixth gate so it stays checked - #176
Merged
Conversation
Two small corrections, both about a page teaching an object the framework has moved on from. `configuration/authorization.md` called `z2ui5_cl_http_handler=>run( )`. That class is the deprecated shim - an empty subclass of `z2ui5_cl_ui5_http_handler`, which is what `get_started/quickstart.md` on this same site already shows and what ships in 1.143.0, the release this site names. Both examples on the page follow quickstart now. The built-in popups are on the deprecation list (`resources/deprecations`, and the popups add-on since 1.142.0), and `cookbook/expert_more/value_help.md` already says so where it uses `Z2UI5_CL_POP_TO_SELECT`. Five other pages used one without a word: exception (`POP_ERROR`), message and logging (`POP_MESSAGES`), pdf (`POP_PDF`) and popup (`POP_TO_CONFIRM`). Each gets the same warning value_help carries - the example stays as it is, because that is what existing code contains, and the reader is told where new code should get its popup from. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
Five pages still described the framework as it was before the release this site names. Everything below was checked against `z2ui5_if_client` at tag 1.143.0 and against a samples checkout. Removed API, still being taught: - `routing.md` opened with `client->set_nav_routing( )` — a METHOD deleted in 1.143.0. Routing is switched on with `follow_up_action( cs_event-set_nav_routing )` now, exactly as samples 468 and 480 do it. The "Navigating by Route" section built on `_event_client( cs_event-nav_to_route )`; that constant is gone too, and the navigation it wrapped is `nav_app_call( )`, which pushes the same route entry. - `frontend.md` listed `nav_to_route` and `history_back` in the `cs_event` block. Neither exists in 1.143.0; both are dropped, and the sentence under the block points at `set_nav_routing` instead. - `url_handling.md` announced "two client methods" for browser history and showed one — `history_back` was the other. It now says one, and shows the raw `history.back()` through `follow_up_action( )` that replaced it. - `nested_views.md` told the reader to call `view_model_update( )` when a nested view looks stale. That method has done nothing since 1.143.0; the push is automatic, which the deprecations page already says and this page contradicted. - `logout.md` used `_event_client( )`, obsolete since 1.143.0, and named `Z2UI5_CL_HTTP_HANDLER` — the empty shim — as the ICF handler class. Samples that do not exist: `Z2UI5_CL_DEMO_APP_139`, `_124` and `_085` (twice) come from a naming scheme the samples repository left behind; no class of that name exists under any prefix. Two are replaced by the real sample for the same thing (`Z2UI5_CL_SMP_APP_322` for push state, `Z2UI5_CL_SMP_APP_098` for the FCL), and the barcode pointer is dropped — the catalogue has no barcode sample to point at. Every remaining `Z2UI5_CL_SMP_APP_*` on the site (98 of them) was verified against the checkout. `authorization.md` and the popup warnings from the previous commit are unaffected; check:examples, check:samples, the anchor sweep and the VitePress build are green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
… names The last commit fixed four pages that taught API 1.143.0 had deleted - `set_nav_routing( )`, `cs_event-nav_to_route`, `cs_event-history_back`, `view_model_update( )`. Finding them took reading every page against the interface at the release tag. Nothing here could have told anybody. `check:examples` is the check that should have, and cannot: it compiles the fenced blocks that are WHOLE CLASSES, and every one of those four lived somewhere it does not reach - a sentence in the prose, a two-line snippet, the `cs_event` block a page reproduces for reference. That is most of what a reader copies. So `check:api-names` asks three questions of every page, against `z2ui5_if_client` fetched at the release this site names (never main - a page is correct when it matches what the reader can install): `client->NAME(` is NAME a method? `NAME = ` inside that call is it one of its parameters? (fenced ABAP only) `cs_GROUP-MEMBER` is MEMBER in that constant group? 1552 names on 137 pages, in about a second. `A2UI5_REF` points it at main for a canary run. Unreachable network SKIPS rather than fails, like check:counts and check:samples - a documentation gate must not go red because github.com is down, and must not claim to have verified what it did not. Pages whose SUBJECT is the removed names are exempt: deprecations, changelog and the action page exist to spell the old spelling, and a gate that forbids that forbids documenting a migration. It found one more page in passing: `navigation.md` named `client->set_nav_routing( )` in a sentence - the fifth site of the same removal, and the one the last commit missed. Wired into `npm run check`, check.yml and deploy.yml in the same position; AGENTS.md's gate table (five -> six) follows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
The User Exits page links `Z2UI5_IF_EXIT` at `abap2UI5/blob/main/src/02/z2ui5_if_exit.intf.abap`. The interface was retired to the frozen `src/99` package when it was superseded by `z2ui5_if_ui5_exit` - it still ships and is still called, it simply is not there any more. Every reader who clicked that link got a 404, on the page whose whole subject is implementing that interface. The link now points where the file is, the tip about the rename says why the path looks frozen, and it links the successor too. `check:api-names` gains the same question for the rest of them: a `github.com/abap2UI5/abap2UI5/blob/main/` link has to resolve. Eight distinct URLs on the site, one HEAD each, and unreachable network skips that question alone rather than the whole gate. Those links say `main`, so `main` is what they are checked against - unlike the three name questions, which are pinned to the release the site names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
…omits The default policy quoted on that page ends `object-src 'none'; base-uri 'self'; frame-ancestors 'self';`. The framework's actual default ends two directives earlier - there is no `frame-ancestors`, and `z2ui5_cl_ui5_user_exit` says why at the line where it is not: " NO frame-ancestors here: browsers IGNORE that directive in a <meta> CSP " (and log a console warning) - cross-origin framing is forbidden by the " real X-Frame-Options: SAMEORIGIN response header set below instead So the page named the wrong mechanism for clickjacking protection, on the page a reader consults precisely to find out what protects them - and handed them that directive twice more to copy: once in the prose list of hardening directives, once in the "drop 'unsafe-eval'" policy the page tells them to paste into their own exit. Pasted, it does nothing but log a warning. All three corrected against the source, and the reason recorded where the question comes up. The mechanism that DOES block framing was undocumented: `t_security_header` is the one `cs_config` field no page mentioned. abap2UI5 sets seven headers on every response - GET and POST alike, `set_response( )` runs after the dispatch in `_main( )` - and they are configurable through the same user exit as the CSP. New "Response headers" section, one row each, with what to do when a proxy already sets one. Everything else the page and its neighbours claim about framework defaults was re-checked and holds: the theme fallback (`sap_horizon`), the bootstrap URL, the 4-hour draft expiry, CSRF on by default. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
`frontend.md` prints the reference table for the control-call events. Its `control_global` row names `MESSAGE_TOAST`, `MESSAGE_BOX`, `BUSY_INDICATOR` and `THEMING`. The whitelist in `core/actions/ControlCall.js` - and the ABAP Doc on `follow_up_action( )` in 1.143.0, which lists all seven - also carries `POPUP`, `INVISIBLE_MESSAGE` and `FORMATTING`. Understating a whitelist is quieter than overstating one and costs more: a reader looking for how to announce something to a screen reader, or how to register a currency the standard type does not know, finds a table that says those are not possible. So the three are added with what they are for and the UI5 floor each needs (1.89 / 1.78 / 1.120), and the `set…` vs `add…` distinction for currencies, which is silent when you pick the wrong one. `VIEW_SLOTS` and `ROUTER` stay out - they are registered in the same map but are framework internals, and the interface does not offer them either. Also: "demo app 470" now names the class, `Z2UI5_CL_SMP_APP_470`, like every other sample reference on the site. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
…orkaround
for a problem that does not exist
All of this came out of reading the model pages against the framework rather
than against themselves.
**`abap_bool` does not travel as `"X"`.** The data-type table says it arrives
as the JSON string `"X"` / `""` and that "UI5's CheckBox expects true/false,
not X" - and the Boolean section of the formatter page builds two workarounds
on that: an expression binding `{= ${/MV_FLAG} === 'X' }`, and a parallel
`string` attribute translated before and after every event.
AJSON maps the boolean ABAP types to a JSON boolean and `boolc( )`s them back
on the way in; `z2ui5_cl_ui5_srv_model`'s own tests assert `"VALIDATED":true`
on the wire, and not one sample in abap2UI5/samples compares a bound value to
`'X'` - they bind `abap_bool` straight onto `selected`. So the first workaround
produces a checkbox that can never tick (it compares against a value that is
not there, and an expression binding cannot write back anyway), and the second
is boilerplate for nothing.
Rewritten to say: bind it directly. With the one thing that genuinely bites
kept - the mapping is keyed on the TYPE, so a flag declared `c LENGTH 1`
travels as a string and stays unchecked - and a pointer to the separate
question of a boolean written into the view as an attribute, where `abap_false`
really does render a control visible and `a( b = … )` is the answer.
**Two more rows of the same table.** `p LENGTH n DECIMALS m` / `decfloat*` are
JSON numbers, not "sent as a string to preserve precision", and `timestamp` /
`timestampl` are numbers too - the framework never turns on AJSON's
`format_datetime`, which is what would make them strings. `utclong` is the one
that is a string, so it gets its own row and a pointer at the formatter that
reads it.
**The binding error is not silent.** Three pages say a `PROTECTED`/`PRIVATE`
attribute passed to `_bind( )` fails silently and that there is "no
compile-time or runtime error", and send the reader to the browser console and
the network tab. `z2ui5_cl_ui5_srv_model=>main_attri_search` raises
BINDING_ERROR - No class attribute for binding found -
Please check if the bound values are public attributes of your class
nothing catches it on the way out, and it lands in the error view. Corrected on
all three, with the "where to look" turned from a hunt into reading the message.
Also on this pass:
- The size-limit page presents all five view slots as independent. MAIN, NEST
and NEST2 share one JSON model through UI5 propagation, so the largest limit
of the three wins and resetting one changes nothing while another asks for
more. Only popup and popover are their own.
- The formatter module the framework ships (`z2ui5/model/formatter` - the four
helpers 26 samples use for `dateValue` and inline icons) was documented
nowhere, while the formatter page told the reader three times to write a
custom JS formatter. It has a section now, including why an empty date must
become `null` and not an `Invalid Date`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
…public half
Six places tell the same story about how state survives a roundtrip, and it is
wrong in both halves.
**Where it goes.** "abap2UI5 serializes the controller TO THE CLIENT and
deserializes it on the next request" (life_cycle), "Browser sends the
serialized app state to the backend" (statefulness), "the controller is
serialized to the client and back" (cheat sheet, common_failures).
`z2ui5_cl_ui5_app_cont=>db_save` hands `all_xml_stringify( )` to
`z2ui5_cl_ui5_srv_draft=>create( )`, which does `MODIFY z2ui5_t_01`. The state
is written to a row in the database and never leaves the server; the browser
carries a draft id, and gets a NEW one on every roundtrip. The one page that
had it right all along is `technical/how_it_all_works` §16, which the others
contradicted.
That is not a detail. A reader who believes their app state crosses the wire
draws conclusions about payload size and about what is exposed to the client,
and both are wrong.
**What survives.** "Only `PUBLIC SECTION` attributes of serializable types
survive", "the framework serializes public attributes after every roundtrip",
"anything stored in public attributes survives". Serialization is
`CALL TRANSFORMATION id` over the whole instance - visibility does not enter
into it. `PUBLIC` is what `_bind( )` needs in order to REACH an attribute, and
nothing else. `z2ui5_cl_smp_app_009` in abap2UI5/samples proves it: it keeps
its whole employee table in the `PROTECTED SECTION`, fills it on init and reads
it back in a later event, and only the filtered copy it binds is public.
The advice that follows from the wrong version is bad advice - it pushes
working state into the public section, where the framework then scans it on
every roundtrip for bindings that do not exist. The framework's own guide says
the opposite ("bound data goes in PUBLIC SECTION, everything else in
PROTECTED"), so the site was arguing with it.
Corrected on all six, plus:
- the walkthrough's step 4, where a beginner meets this first, and where the
same "silently ignores private or protected ones" from the last commit had
survived
- "Two-way" -> "both directions", the wording the ecosystem retired
- common_failures gains the two things a reader in that situation needs: that
a serialization failure is reported (`APP_SERIALIZATION_ERROR`), and that
the draft expires after four hours
- `how_it_all_works` §16 now names the table, `Z2UI5_T_01` - the diagrams
still show the working name `z2ui5_t_draft`, which is worth saying once
Checked and found correct on this pass, so noted rather than touched:
`follow_up_action( )`'s raw-JS discrimination rule (the page's
`A-Z a-z 0-9 _` matches the `CO` test in the source character for character),
the view-definition page's account of what the builder does and does not
enforce, and the `check_on_event` once-per-roundtrip section.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJBaqq5cFVUVMGr1BQvSVC
…erungen-fixes-ovyryc # Conflicts: # docs/get_started/full_example.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eight commits, all from one method: read each page against
z2ui5_if_clientat the release this site names, and against the framework source, rather than against itself.The corrections
abap_booldoes not travel as"X". The data-type table said it arrives as the JSON string"X"/"", and the Boolean section built two workarounds on that: an expression binding{= ${/MV_FLAG} === 'X' }, and a parallelstringattribute translated before and after every event. AJSON maps the boolean ABAP types to a JSON boolean andboolc( )s them back;z2ui5_cl_ui5_srv_model's own tests assert"VALIDATED":trueon the wire, and not one sample in abap2UI5/samples compares a bound value to'X'— they bindabap_boolstraight ontoselected. The first workaround can never tick a box; the second is boilerplate for nothing. Rewritten to "bind it directly", keeping the thing that does bite: the mapping is keyed on the type, so a flag declaredc LENGTH 1travels as a string.The app state does not travel to the browser, and it is not only the public half. Six places said the controller is "serialized to the client and back" and that only
PUBLIC SECTIONattributes survive.db_savehandsall_xml_stringify( )toz2ui5_cl_ui5_srv_draft=>create( ), which doesMODIFY z2ui5_t_01: the state is a row in the database and never leaves the server; the browser carries a draft id and gets a new one every roundtrip. And serialization isCALL TRANSFORMATION idover the whole instance —PUBLICis what_bind( )needs to reach an attribute, not what keeps it alive (z2ui5_cl_smp_app_009keeps its whole employee table protected across events). The advice that followed from the wrong version pushed working state into the public section, which is the opposite of what the framework's own guide says.The binding error is not silent. Four pages said a
PROTECTED/PRIVATEattribute passed to_bind( )fails silently with "no compile-time or runtime error", and sent the reader to the browser console.main_attri_searchraisesBINDING_ERROR - No class attribute for binding found …, nothing catches it, and it lands in the error view.The Security page credited a CSP directive the framework deliberately omits. The quoted default policy ended
frame-ancestors 'self'; the framework stops two directives earlier and says why at the line where it is not — browsers ignoreframe-ancestorsin a<meta>CSP, so framing is blocked by theX-Frame-Optionsheader instead. The page named the wrong mechanism and handed the reader that directive twice more to copy. Also:t_security_headerwas the onecs_configfield no page mentioned, so the seven response headers the framework sets now have a section.API that 1.143.0 removed, still being taught on five pages:
client->set_nav_routing( )(a deleted method) inrouting.mdandnavigation.md,cs_event-nav_to_routeandcs_event-history_backin thecs_eventblock and the browser-history section,view_model_update( )recommended as a fix innested_views.md,_event_client( )and theZ2UI5_CL_HTTP_HANDLERshim inlogout.mdandauthorization.md.Smaller ones:
control_globalhas seven whitelisted objects, the reference table listed four (POPUP,INVISIBLE_MESSAGEandFORMATTINGwere missing — understating a whitelist tells the reader something is impossible);p/decfloat*andtimestamp/timestamplare JSON numbers, not strings; the User Exits page linkedZ2UI5_IF_EXITat a path it left when it was retired tosrc/99, so the link 404'd; four references toZ2UI5_CL_DEMO_APP_*classes that exist under no prefix; the size-limit page presented all five view slots as independent whenMAIN/NEST/NEST2share one model and the largest limit wins; and the formatter module the framework ships (z2ui5/model/formatter— the four helpers 26 samples use) was documented nowhere, while the formatter page told the reader three times to write a custom JS formatter.The gate
Finding those took reading every page against the interface at the release tag.
check:examplesis the check that should have caught them and cannot: it compiles the fenced blocks that are whole classes, and almost every one of these lived somewhere it does not reach — a sentence, a two-line snippet, a constant block reproduced for reference. That is most of what a reader copies.check:api-namesasks four questions of every page, againstz2ui5_if_clientfetched at the release this site names:1543 names and 8 source links across 137 pages, in about a second. Truth is the release, never main — a page is correct when it matches what the reader can install;
A2UI5_REFpoints it at main for a canary run. Unreachable network skips rather than fails, likecheck:samples. Pages whose subject is the removed names (deprecations, changelog, the action page) are exempt, or the gate would forbid documenting a migration.Wired into
npm run check,check.ymlanddeploy.ymlin the same position; the gate table inAGENTS.mdgoes from five to six.How to test
npm run check. All six gates green on this branch, including against the ten-step walkthrough and the new home page that landed on main in the meantime.Generated by Claude Code