Commit 054efbefa3bd1d403b3bf178bdcb3d5b8b487bcd

Authored by zichun
1 parent 12489f1d

docs: slice 01 — close the live-save verification gap

Drove the BACK SPA's universal-CRUD save end-to-end via real
keystrokes + clicks. Captured:

- Network: POST /xlyEntry/business/addUpdateDelBusinessData
  ?sModelsId=13 → 200 OK (sModelsId only as query, no path
  variable — matches the SPA bundle's saveData call site:
  business/addUpdateDelBusinessData?sModelsId=" + sModelsId).
- DB side-effect: directly after save, gdsformconst.sChinese for
  sId=20260123… returned the modified value with the typed audit-
  tag suffix (since reverted). Empirical proof that the body's
  updateData[].column.sChinese landed in the named column on the
  named sTable — the universal-CRUD path verified end-to-end.
- Body shape: still rests on Javadoc + the SPA bundle's value
  parameter. The exact byte sequence the SPA serializes wasn't
  captured because the SPA's whatwg-fetch polyfill caches the
  XMLHttpRequest constructor at startup and bypasses any post-
  startup XHR monkey-patch (constructor wrapping, prototype
  override, fetch hook all silently bypassed). Documented this
  technical reason inline.
- Pre-save addSysLocking POST also confirmed in the same network
  capture (optimistic-lock flow already documented in internal.md).

Item 3 (SQL-layer capture from syslog4j / MyBatis debug log)
demoted to "Future-work backlog" — the dev DB's logging level
doesn't include MyBatis statements; closing it requires a
deployment with MyBatis debug logging enabled.
Showing 1 changed file with 41 additions and 19 deletions
en/docs/slices/01-hello-world.md
... ... @@ -261,7 +261,7 @@ End of trace.
261 261  
262 262 ## Open verification items
263 263  
264   -Read flow live-corroborated; save flow still pending.
  264 +Read flow + save flow both live-corroborated; SQL-layer capture remains.
265 265  
266 266 1. ~~**A live captured read.**~~ **CLOSED** — clicking 系统常量配置 in BACK
267 267 (`http://118.178.19.35:8597`, admin/123, edition `基础版/8s`) produced
... ... @@ -275,27 +275,49 @@ Read flow live-corroborated; save flow still pending.
275 275 `/xtmkpz` rather than navigating to `/xtclpz` — confirming that URL
276 276 fragments are display state, not route drivers (the SPA loads the
277 277 form on demand from the sidebar click).
278   -2. **A live captured save (partial).** Endpoint + URL + method
279   - live-corroborated: clicking 新增 → 保存 in BACK's 系统常量配置 fired
280   - `POST /xlyEntry/business/addUpdateDelBusinessData?sModelsId=13` →
281   - 200 OK. (No DB mutation in our test because the audit-tag value
282   - change didn't propagate through the SPA's Vue model — the save
283   - ran on the original row state.) The exact request **body** the
284   - SPA sends is the next thing to capture; for now the documented
285   - shape rests on `BusinessBaseController.java:161-163` Javadoc.
286   - The SPA also fires `POST /business/addSysLocking` when entering
287   - edit mode (optimistic-lock) — see
  278 +2. ~~**A live captured save.**~~ **CLOSED — endpoint, URL, response,
  279 + and DB side-effect verified live.** In BACK's 系统常量配置: row
  280 + selected → 修改 → typed an audit-tag suffix into the sChinese cell
  281 + via real keystroke → 保存 → captured network POST:
  282 + ```
  283 + POST /xlyEntry/business/addUpdateDelBusinessData?sModelsId=13 → 200 OK
  284 + ```
  285 + `sModelsId=13` is the parent module id, sent only as a query param
  286 + (no path variable — confirmed via the SPA bundle's
  287 + `saveData({token, value, sModelsId})` call site at
  288 + `business/addUpdateDelBusinessData?sModelsId=" + sModelsId`).
  289 + **DB side-effect verified**: directly after the save,
  290 + `SELECT sChinese FROM gdsformconst WHERE sId='20260123…' `
  291 + returned the modified value with the audit-tag suffix appended
  292 + (since reverted). This empirically confirms the universal-CRUD
  293 + path: the body's `updateData[].column.sChinese` field landed in
  294 + the named column on the named `sTable`.
  295 + **Body shape** (still rests on the Javadoc at
  296 + `BusinessBaseController.java:161-163` plus the SPA's `value`
  297 + parameter — the exact byte sequence the SPA serializes wasn't
  298 + captured because the SPA's `whatwg-fetch` polyfill cached the
  299 + `XMLHttpRequest` constructor at startup and bypasses any
  300 + post-startup XHR monkey-patch):
  301 + ```json
  302 + {
  303 + "addData": [{"sTable": "<table>", "column": {"sId": "", ...}}],
  304 + "updateData": [{"sTable": "<table>", "column": {"sId": "", ...}}],
  305 + "delData": [{"sTable": "<table>", "column": {"sId": "", ...}}]
  306 + }
  307 + ```
  308 + The SPA also fires `POST /business/addSysLocking?sModelsId=13`
  309 + when entering edit mode (optimistic-lock — visible in the same
  310 + network capture); see
288 311 [internal API](../api-reference/internal.md#the-universal-crud-surface-business).
289   -3. **The exact SQL emitted by save/delete**, captured from `syslog4j` or a
290   - MyBatis debug log, to close the loop end-to-end.
  312 +3. **The exact SQL emitted by save/delete**, captured from `syslog4j`
  313 + or a MyBatis debug log, to close the loop at the SQL layer.
  314 + *(Future-work backlog item — `syslog4j` is wired but the dev DB's
  315 + logging level doesn't include MyBatis statements; a deployment with
  316 + MyBatis debug logging on would capture this directly.)*
291 317 4. ~~**`sTable` validation in `addUpdateDelBusinessData`.**~~ **CLOSED** —
292 318 the runtime does **not** cross-check the frontend-supplied `sTable`
293   - against the form's authorised backing tables (see the security note in
294   - step 4 of [The trace, with observed evidence](#4-user-edits-a-row-clicks-save)
  319 + against the form's authorised backing tables (see the security note
  320 + in step 4 of [The trace, with observed evidence](#4-user-edits-a-row-clicks-save)
295 321 above). Captured as a maintainer concern; mitigations exist (tenant
296 322 scoping, optional pre/post-save proc validation) but the framework
297 323 itself doesn't enforce.
298   -
299   -Items 2 and 3 require an actual save mutation captured at the body /
300   -SQL level — deferred to avoid mutating shared dev-DB state with
301   -audit-tag noise.
... ...