From 8b728295a95c49a71e830bf7b15aa08357e43ea3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Aug 2026 20:43:24 +0800 Subject: [PATCH] docs(plan): refine modal runtime seams Co-Authored-By: Claude Fable 5 --- .specs/plans/frontend-modal-runtime.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.specs/plans/frontend-modal-runtime.md b/.specs/plans/frontend-modal-runtime.md index 31d7cf83..5fc34207 100644 --- a/.specs/plans/frontend-modal-runtime.md +++ b/.specs/plans/frontend-modal-runtime.md @@ -7,6 +7,8 @@ - **Cache contract**: Use in-memory, user-scoped cache entries with short TTLs, in-flight request deduplication, explicit invalidation tags, and complete clearing on logout/account switch. Do not persist private modal payloads in localStorage. - **State contract**: All domains use the same `idle`, `loading`, `ready`, `empty`, `submitting`, `success`, `error`, `unauthorized`, and `stale` states. Skeletons match the final layout and never represent business truth. - **API boundary**: Existing `aksrt/v1` domain routes remain the service boundary; HTML modal responses are replaced domain by domain with minimal JSON view models. Every changed REST route keeps a `permission_callback`; AJAX is not a new data path. +- **Request adapter**: Add one thin `AksrtRequest` adapter for the injected REST root, nonce headers, JSON/error envelopes, 401 handling, and abort signals. Domain files stop maintaining their own REST-root and response-parsing variants. +- **Rehydrate and feedback**: Remote HTML that remains during migration must call `AksrtFrontend.rehydrate(body, 'modal')`; shared feedback must call the existing callable `AksrtToast` API (with `aksrtNotify`/alert fallback), not assume an incompatible `.show` method. Runtime binding must be idempotent so `pay-vip.js` does not register both registry and immediate fallback handlers. - **Rollout**: Add a temporary per-domain rollout section under the existing Tools configuration surface, read through `AKSRT_Settings`. One canonical new implementation is enabled per domain; the switch is for staged release, not a compatibility data layer. - **Telemetry**: Use browser `performance.mark/measure` and server `Server-Timing`/existing deployment observability by default. Do not add a private payload or payment/identity-content event store in this foundation plan. - **Build boundary**: Frontend assets are plain theme JavaScript, not the Admin SPA bundle. Run `node --check` for changed JS and run the admin contract audit only when the rollout schema/controller changes. @@ -42,14 +44,14 @@ Primary integration points: ### What to build -Refactor `AksrtRemoteModal` in `assets/js/core/remote-modal.js` into the canonical runtime while preserving its existing visual shell as the first implementation. Add focused runtime modules for loader registration, cache/state, and telemetry integration. The runtime must support a skeleton before data, JSON or HTML during the migration boundary, abort signals on close/replacement, request deduplication, explicit invalidation, focus return, keyboard/overlay close, mobile bottom-sheet behavior, and retryable errors. Wire the existing generic remote-modal trigger set through this runtime and inventory every remaining caller before domain migrations begin. +Refactor `AksrtRemoteModal` in `assets/js/core/remote-modal.js` into the canonical runtime while preserving its existing visual shell as the first implementation. Add focused runtime modules for loader registration, cache/state, telemetry integration, and the `AksrtRequest` adapter. The runtime must support a skeleton before data, JSON or HTML during the migration boundary, abort signals on close/replacement, request deduplication, explicit invalidation, focus return, keyboard/overlay close, mobile bottom-sheet behavior, and retryable errors. When HTML is still returned, invoke `AksrtFrontend.rehydrate` for modal-scoped handlers and route notifications through the callable Toast adapter. Wire the existing generic remote-modal trigger set through this runtime, make feature registration idempotent, remove the pay-vip registry/immediate-bind double path, and inventory every remaining caller before domain migrations begin. ### Done when -- [ ] `assets/js/core/remote-modal.js` exposes one canonical `AksrtModalRuntime.open/close/refresh` lifecycle and the new loader/cache/state modules are imported by the changed entry point; no domain script creates a second global modal host. -- [ ] `node --check assets/js/core/remote-modal.js assets/js/core/modal-runtime.js assets/js/core/modal-cache.js assets/js/core/modal-state.js` passes, using the actual new filenames if the implementation keeps the runtime in the existing file. -- [ ] Browser scenario `modal-shell-lifecycle` verifies shell visibility within the 100ms initial budget, skeleton/error/retry states, ESC and overlay close, focus return, request cancellation, and mobile bottom-sheet behavior. -- [ ] Browser scenario `modal-cache-dedupe` verifies one read for concurrent/repeated opens, invalidation after a successful write, and no reuse after logout/account switch; `git grep -n "AksrtRemoteModal\|data-toggle=\"AksrtRemoteModal\"\|data-aksrt-remote-modal"` produces an explicit migration inventory. +- [ ] `assets/js/core/remote-modal.js` exposes one canonical `AksrtModalRuntime.open/close/refresh` lifecycle, `AksrtRequest` owns REST root/nonce/envelope handling, and no domain script creates a second global modal host. +- [ ] `node --check assets/js/core/remote-modal.js assets/js/core/request.js assets/js/core/modal-runtime.js assets/js/core/modal-cache.js assets/js/core/modal-state.js assets/js/pay-vip.js` passes, using the actual new filenames if the implementation keeps modules consolidated. +- [ ] Browser scenario `modal-shell-lifecycle` verifies shell visibility within the 100ms initial budget, skeleton/error/retry states, ESC and overlay close, focus return, request cancellation, mobile bottom-sheet behavior, callable Toast fallback, and `AksrtFrontend.rehydrate(body, 'modal')` after remote HTML. +- [ ] Browser scenario `modal-cache-dedupe` verifies one read for concurrent/repeated opens, invalidation after a successful write, no reuse after logout/account switch, and one pay-vip binding; `git grep -n "AksrtRemoteModal\|data-toggle=\"AksrtRemoteModal\"\|data-aksrt-remote-modal"` produces an explicit migration inventory. ---