From f8d6cdf1d860c868b614e61ac315dc02ee947a4d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 25 May 2026 12:02:55 +0000 Subject: [PATCH] docs(ensemble): document storage.clear and multipart upload paths Describe ensemble.storage.clear() semantics (enc_ keys, binding dispatch, async clear), uploadPathContainsParentSegment for file uploads, and align the module README index with the expanded runtime-security doc. Co-authored-by: Sharjeel Yunus --- modules/ensemble/README.md | 2 +- .../runtime-security-and-data-bindings.md | 54 ++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/modules/ensemble/README.md b/modules/ensemble/README.md index 4309e5ef2..46e742b1c 100644 --- a/modules/ensemble/README.md +++ b/modules/ensemble/README.md @@ -76,7 +76,7 @@ This package has a substantial `test/` directory. Run package tests with `melos ## Additional technical documentation - [Layout widgets (tabs, ListView scroll)](docs/layout-widgets.md) — EDL layout behavior in `lib/layout`. -- [Runtime security and data bindings](docs/runtime-security-and-data-bindings.md) — screen id validation for definition providers, `saveFile` naming, WebView TLS/reputation settings, global script handler payloads, and device metric bindings after rotation. +- [Runtime security and data bindings](docs/runtime-security-and-data-bindings.md) — screen id validation for definition providers, `saveFile` naming, multipart upload path checks, `ensemble.storage.clear()` behavior and binding refresh, WebView TLS/reputation settings, global script handler payloads, and device metric bindings after rotation. ## Related Packages / Modules diff --git a/modules/ensemble/docs/runtime-security-and-data-bindings.md b/modules/ensemble/docs/runtime-security-and-data-bindings.md index 2d1588c1a..3b5e6c9d2 100644 --- a/modules/ensemble/docs/runtime-security-and-data-bindings.md +++ b/modules/ensemble/docs/runtime-security-and-data-bindings.md @@ -1,8 +1,9 @@ # Runtime security and data bindings This document describes **verified** runtime behavior for definition loading, -file writes, WebView hardening, global JavaScript handlers, and device metric -bindings. Implementation lives under `modules/ensemble` unless noted. +file writes, multipart uploads, public app storage clears, WebView hardening, +global JavaScript handlers, and device metric bindings. Implementation lives +under `modules/ensemble` unless noted. ## Screen names for local and remote definitions @@ -51,6 +52,55 @@ base name is allowed. `test/save_file_name_test.dart` covers `sanitizedSaveFileName`. +## Multipart upload paths + +`lib/util/upload_utils.dart` rejects local file paths that contain a `..` path +segment (after normalising backslashes to forward slashes) before calling +`http.MultipartFile.fromPath`. The intent is to block partially trusted paths +(for example from API JSON bound into file upload actions) from traversing +outside an intended directory when bytes are read from disk. + +### Runtime effect + +`UploadUtils.uploadFiles` throws `FormatException` with a message that includes +the offending path when any upload item has a non-null `path` that fails this +check. + +### Tests + +`test/upload_path_security_test.dart` covers `uploadPathContainsParentSegment`. + +## `ensemble.storage.clear()` and UI bindings + +`EnsembleStorage` (`lib/framework/data_context.dart`) exposes invokable methods +including `get`, `set`, `delete`, and **`clear`**, backed by **public** +`GetStorage` through `StorageManager` (`lib/framework/storage_manager.dart`). +System storage and secure storage are separate; `clear` only affects public +app-developer storage. + +### What `clear` removes + +`clearPublicStorage` removes every key in the default `GetStorage` box **except** +keys whose names start with the literal prefix **`enc_`**. Those entries are +treated as a reserved namespace and are left in place. Only the `enc_` prefix +is special; for example a key named `enc2` is **not** treated as encrypted and +**is** removed. + +### Binding refresh + +Before removal, the runtime collects dispatch keys with +`ensembleStorageClearDispatchKeys` (same `enc_` filter). It then invokes +`clearPublicStorage` and, **without awaiting** that `Future`, immediately calls +`ScreenController.dispatchStorageChanges` once per collected key with a `null` +value so `StorageBindingSource` listeners (for example +`${ensemble.storage.someKey}` on the current page) refresh. Do not assume a +fixed ordering between persistence finishing and UI updates across platforms. + +### Tests + +- `test/ensemble_storage_clear_test.dart` — dispatch key selection for `clear`. +- `test/storage_manager_test.dart` — parity logic for which keys survive a clear. + ## Native `WebView` (InAppWebView) TLS and reputation `lib/widget/webview/native/webviewstate.dart` configures `InAppWebViewSettings`.