You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Squash-rebased #103698 segment onto the typed-actions tip on current main.
Adds the tokenless /approve/{id} standalone approval UI served by the
gateway control-UI router, gateway-store ephemeral login fix (selectGateway
only on changed URL), and approval-page i18n strings.
Drift reconciliation: union-merged i18n translation-memory caches and
regenerated locale metadata via control-ui-i18n sync (33 approvalPage keys
remain English fallbacks in minor locales, as on the original branch).
(cherry picked from commit c82f56011bfe9f0debb8ebe052f14590c187340d)
(cherry picked from commit 80f5636a8b67a3d6a5f330620541a39d4ef3fe6f)
(cherry picked from commit a3e300d337a92bf1b593a0bb52b7ec4549910a21)
(cherry picked from commit 860ad01f9658bba54cb3d59644e5e1a032c0bb3f)
(cherry picked from commit d8b697b28a847950a1797da07fc0ae4c24928492)
(cherry picked from commit 8a654e3271fd5721358812f961a7a7bb386d6726)
(cherry picked from commit 2f776d2e7bf910271fcbd9697597f6f5478b0f30)
(cherry picked from commit 14e64e6e4d763be830830801eeec1a6f17441688)
(cherry picked from commit 4df9ec828d0034fdc76540ff0fe341e599b0f281)
(cherry picked from commit e52968f)
(cherry picked from commit 7214fc25013966f99ff4b2d506aa2f5f789e2113)
(cherry picked from commit c6259ff79787c759c136086e1a54c9ead8e89539)
(cherry picked from commit a58d9f271d27481615f0c94a828704c563d5354f)
(cherry picked from commit dcf1cb6)
|`approval.get { id }`| Returns a visible pending or retained terminal projection. |
167
167
|`approval.resolve { id, kind, decision }`| Accepts the canonical ID or fixed-size transport reference, then runs authorization, kind and allowed-decision validation, deadline reconciliation, and terminal CAS. The response always carries the canonical ID. |
168
168
169
+
After a successful CAS, return the committed projection immediately. Legacy events, channel forwarders, and push terminalizers are best-effort follow-ups; a slow or failed surface must not delay or roll back the winning response.
170
+
169
171
Kind-specific request validation remains in `exec.approval.request` and `plugin.approval.request`. Existing `exec.approval.get/list/waitDecision/resolve` and `plugin.approval.list/waitDecision/resolve` become protocol-boundary adapters to the canonical service because they are shipped Gateway API. Internal callers migrate to the service in the same change.
170
172
171
173
A reviewer projection is a tagged union:
@@ -229,6 +231,8 @@ The route is `${basePath}/approve/{approvalId}`. The ID is the only path paramet
229
231
230
232
Because the current router has exact static routes and rewrites unknown paths to Chat, detect this deep link in `ui/src/app/bootstrap.ts` before normal route normalization. Reuse normal Gateway/auth setup, but render a standalone approval page outside the sidebar shell and global modal.
231
233
234
+
The document is owned by the Gateway that served its URL. Its initial connection ignores the full app's persisted remote-Gateway selection without changing or copying that selection's settings; only auth stays session-scoped to the serving Gateway. Trusted native auth or a separately confirmed `gatewayUrl` override may retarget it. The core reserves the one-segment `/approve` namespace ahead of plugin HTTP routes and static-extension detection, including IDs that end in `.json` or `.js`; when Control UI serving is disabled, the reserved route fails closed with `404`. Keep the page in the main Control UI bundle so a failed lazy chunk cannot strand a security decision on a spinner.
235
+
232
236
Page states:
233
237
234
238
- loading
@@ -371,6 +375,8 @@ Do not silently change them in the storage PR. The strict-semantics PR must upda
371
375
### PR 3: Control UI deep link
372
376
373
377
- Standalone authenticated approval page and base-path-aware startup routing.
378
+
- Serving-Gateway binding without mutating the operator's saved remote selection.
379
+
- Core-owned approval HTTP namespace, including asset-like IDs.
374
380
- Gateway-authored URL payload and pending-state polling until lifecycle events ship.
375
381
- Mobile-width, reconnect, competing-answer, reload, and mounted-path proof.
Copy file name to clipboardExpand all lines: docs/web/control-ui.md
+8-1Lines changed: 8 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -568,7 +568,14 @@ When gateway auth is configured, assistant local-media previews use a two-step r
568
568
569
569
This keeps media rendering compatible with browser-native media elements without putting reusable gateway credentials in visible media URLs.
570
570
571
-
## Building the UI
571
+
## Approval links
572
+
573
+
Operator approval notifications can deep-link to a standalone approval document served under the reserved `${controlUiBasePath}/approve/{approvalId}` namespace (for example `/approve/<approvalId>`, or `/openclaw/approve/<approvalId>` with a configured base path). The URL is stable for the lifetime of the approval and safe to forward between your own devices: it identifies the approval, never authorizes it.
574
+
575
+
- The one-segment `/approve/<approvalId>` namespace is reserved by the Gateway ahead of plugin HTTP routes for **all** HTTP methods, so a plugin route can never shadow or intercept an approval document.
576
+
- Opening an approval document requires the same gateway auth as the rest of the Control UI (token/password, Tailscale Serve identity, or trusted-proxy identity); credentials are never part of the approval URL.
577
+
- When Control UI serving is disabled, requests to the namespace return `404` instead of falling through to plugin handlers.
578
+
- Signing in on an approval document is ephemeral for that page: it does not overwrite the gateway selection or settings saved by the full Control UI in the same browser.
572
579
573
580
The Gateway serves static files from `dist/control-ui`:
0 commit comments