Skip to content

Workspaces: add full-bleed apps and guarded gallery installs#101908

Closed
100yenadmin wants to merge 6 commits into
openclaw:mainfrom
100yenadmin:feat/dashboard-apps-layer
Closed

Workspaces: add full-bleed apps and guarded gallery installs#101908
100yenadmin wants to merge 6 commits into
openclaw:mainfrom
100yenadmin:feat/dashboard-apps-layer

Conversation

@100yenadmin

@100yenadmin 100yenadmin commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Workspaces can render custom widgets, but users still lacked an app-like full-tab layout and a safe way to discover and stage third-party widget bundles. The old implementation fetched gallery content in the browser, which made the trust boundary unclear and did not provide a server-owned network policy suitable for a shared gateway.

Why This Change Was Made

This rebuild keeps full-bleed tabs and moves gallery retrieval into the Workspaces plugin under an explicit operator-controlled policy:

  • galleries are disabled until gallery.allowedOrigins contains exact normalized HTTPS origins;
  • server fetches use the shared SSRF guard with strict public-address checks and pinned DNS, a five-second timeout, no ambient credentials, and a synchronous per-hop redirect validator invoked before each redirect target is followed; allowlisting an origin does not opt into RFC1918 or ULA access;
  • the shared SSRF guard now supports synchronous per-hop redirect validation; Workspaces uses it to enforce the exact HTTPS-origin allowlist without treating allowlisting as permission to access private networks;
  • redirects are limited to three hops and every destination must remain HTTPS and match the allowlist before a follow-up request is made;
  • registry and bundle responses are JSON-only and bounded by byte, schema, URL, manifest, file-count, file-size, and normalized-path limits;
  • gallery listing is read-scoped, while installation requires operator.approvals;
  • installation rejects non-child names, acquires an owned create-new reservation inside the target, and writes every bundle file with create-new semantics while holding the cross-process per-widget lock;
  • gallery and local scaffold installs share a per-widget reservation, closing the cross-path replacement race;
  • installation creates only a validated, exclusive bundle and a pending registry entry;
  • the existing separate widget approval step freezes hashes before that exact snapshot may render.

Fetching, listing, and installing never mount or execute widget code.

User Impact

Users can turn a tab into a focused full-bleed app surface and browse an operator-approved widget gallery. A malicious registry cannot redirect the gateway to an unapproved origin, send credentials, escape the widget directory, exceed the bounded payload contract, or activate code merely by being fetched or installed. Operators retain an explicit second approval before any installed widget can render.

Enabling a gallery intentionally makes the OpenClaw gateway contact the configured origin, which can observe the gateway IP address and requested paths. These requests carry no ambient credentials, OpenClaw authentication, or telemetry.

Evidence

  • Rebased onto upstream main at a03df5fd5898e24facd38c07d9d9e60a047f0111, frozen for the final batch; all six functional commits are patch-equivalent to the validated stack, and the history-only cleanup leaves the exact final tree unchanged while removing a fully reverted dependency-patch detour.
  • Final-head infra proof: 2 files / 134 tests passed, including synchronous validation before a redirect target is resolved or contacted and mutation-resistant redirect callback inputs.
  • Final-head Workspaces extension proof: 6 files / 56 tests passed, covering redirects, MIME and body bounds, unsafe and non-child paths, symlink rejection, successful and ambiguous-failure reservation retention, gallery/scaffold serialization, hashed lock-name isolation, direct-filesystem no-clobber and competitor-content preservation, pending-only registration after the complete tree exists, and read/approval scopes.
  • Workspaces UI proof: 1 file / 12 tests passed from the canonical ui package working directory, including builtin and custom full-bleed layout behavior.
  • Core production/test and extension production/test type checks passed on the validated security delta; final-head plugin SDK API-baseline verification, targeted formatting/lint, and git diff --check are clean.
  • The focused SDK surface contains exactly three new non-deprecated SSRF exports; API-baseline verification and the complete surface report passed at 10,648 public exports, 5,358 callable exports, 3,282 deprecated exports, and 209 wildcard exports.
  • Multiple structured/security review rounds found concrete issues in staging cleanup, canonical test invocation, cross-path install exclusivity, an unsafe exclusive-directory fallback, overwrite-on-rename behavior, and cleanup of path names whose ownership became ambiguous. The added filesystem primitive and overwrite publish were removed; gallery now owns the target with a create-new marker, retains that hidden non-servable marker instead of deleting an ambiguously owned pathname, never overwrites or deletes a competitor file, leaves partial failures unregistered, and withholds pending registry state until every expected file exists.
  • No package manifest, dependency patch, or lockfile changes remain in the PR. The repository-prescribed dependency delta report for exact head a6749eb96293e8cd82b92a28edcac04e1130e289 confirms 0 added, 0 removed, and 0 changed resolved packages and 0 dependency-file changes.
  • Hosted broad validation remains GitHub Actions' responsibility because Testbox was unavailable locally.

Closes #101148 and #101149.

@100yenadmin
100yenadmin requested a review from a team as a code owner July 7, 2026 23:26
@100yenadmin

Copy link
Copy Markdown
Contributor Author

On dependency-guard: inherited from the unmerged Wave 1 base (#101098) — no new dependency. Gallery install is client-fetch only (a source-scan guard test proves the gateway never fetches a URL — no SSRF); installs land pending → the existing approval gate → sandbox. Verified by the submitting orchestrator's own gate + security review: extensions/dashboard 92 tests, UI dashboard suites green (3 unrelated pre-existing terminal-panel browser flakes), ui:build + full type-aware oxlint clean.

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@github-actions github-actions Bot added the dependencies-changed PR changes dependency-related files label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: a6749eb96293e8cd82b92a28edcac04e1130e289

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 13, 2026, 9:02 AM ET / 13:02 UTC.

Summary
The PR adds full-bleed Workspaces tabs, server-guarded widget gallery listing and installation, shared install locking, SSRF redirect validation, plugin configuration, documentation, and focused tests.

PR surface: Source +702, Tests +837, Docs +47, Generated 0, Other -1. Total +1585 across 29 files.

Reproducibility: not applicable. as a bug reproduction: this PR adds new Workspaces behavior. Focused tests exercise the designed paths, but the complete real user flow has not been demonstrated on the current head.

Review metrics: 2 noteworthy metrics.

  • Configuration Surface: 1 optional array added. gallery.allowedOrigins becomes a durable operator-facing network policy and documentation contract.
  • Plugin SDK Surface: 3 exports added. External plugins may come to depend on the new guarded-fetch option, redirect, and result types.

Stored data model
Persistent data-model change detected: database schema: extensions/workspaces/src/cli.test.ts, database schema: extensions/workspaces/src/gallery.test.ts, database schema: extensions/workspaces/src/gallery.ts, serialized state: extensions/workspaces/src/gallery.test.ts, serialized state: extensions/workspaces/src/scaffold.ts, serialized state: ui/src/pages/plugin/workspace-view.test.ts, and 1 more. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted current-head live proof of full-bleed, gallery listing, installation, pending approval, and no auto-mount.
  • Provide a safe operator-visible retry or cleanup path for retained failed-install reservations.
  • Obtain explicit maintainer sponsorship for the gallery configuration and public SSRF SDK surface.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR supplies automated tests, type and lint checks, API-baseline output, and dependency evidence only; add redacted current-head screenshots, a recording, terminal live output, or logs showing full-bleed plus gallery browse, install, pending, and no-auto-mount behavior. Updating the PR body should trigger review, or a maintainer can request @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Failed or interrupted installation can retain a partial reserved widget path, leaving that widget name blocked until an operator manually understands and repairs state-directory contents.
  • [P1] The PR adds one operator-facing network-policy configuration surface and three public SSRF plugin-SDK exports whose long-term compatibility and ownership are not settled by CI.
  • [P1] The gallery makes the Gateway contact configured third-party origins and stage untrusted bundle files, so maintainers must explicitly accept the trust model despite its strong SSRF, bounds, path, locking, and approval defenses.
  • [P1] Automated tests do not prove the complete current-head browse, install, pending, approval, and no-auto-mount user journey.

Maintainer options:

  1. Repair And Sponsor The Complete Feature (recommended)
    Add safe recovery, approve the configuration and API direction, and provide live current-head proof before merge.
  2. Split The Low-Risk Layout Work
    Move full-bleed tabs into a narrow PR and pause gallery networking, installation, and SDK changes for separate review.
  3. Pause The Gallery Direction
    Close or defer the gallery portion if maintainers do not want OpenClaw to own this server-side distribution trust model.

Next step before merge

  • [P1] Maintainers must choose the gallery, configuration, and SDK direction; the contributor then needs safe recovery and real current-head behavior proof before merge.

Maintainer decision needed

  • Question: Should Workspaces ship an operator-configured server-side widget gallery together with a new public SSRF redirect-validation plugin API?
  • Rationale: This creates a permanent distribution feature, configuration contract, Gateway network trust boundary, and public plugin API; implementation quality and tests cannot determine whether OpenClaw should own those surfaces.
  • Likely owner: steipete — The decision crosses Workspaces product scope, operator configuration, security policy, and permanent public plugin-SDK ownership.
  • Options:
    • Sponsor Guarded Gallery (recommended): Approve the server-side gallery and public SDK direction after recovery and live-proof blockers are closed.
    • Land Full-Bleed Only: Split out the full-bleed tab layout and defer gallery distribution and SDK expansion.
    • Externalize Distribution: Keep discovery and publishing in ClawHub or another plugin-distribution surface rather than adding a Workspaces-owned gallery contract.

Security
Needs attention: The branch adds strong SSRF, redirect, bounds, path, locking, and approval defenses, but retained installation state and the permanent public trust contract still need resolution.

Review findings

  • [P2] Add a supported recovery path for retained install reservations — extensions/workspaces/src/gallery.ts:388
Review details

Best possible solution:

Either split and land the bounded full-bleed layout separately, or sponsor the complete gallery only after adding a safe in-product or doctor-owned recovery path, approving the configuration and public SDK contracts, and attaching redacted current-head live proof.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a bug reproduction: this PR adds new Workspaces behavior. Focused tests exercise the designed paths, but the complete real user flow has not been demonstrated on the current head.

Is this the best way to solve the issue?

No, not yet. Moving gallery fetches behind the shared SSRF guard is safer than browser fetching, but retained-install recovery and the need for a permanent public SDK callback must be resolved or explicitly accepted first.

Full review comments:

  • [P2] Add a supported recovery path for retained install reservations — extensions/workspaces/src/gallery.ts:388
    The installer intentionally keeps the reserved widget directory after ambiguous or partial failures to avoid deleting a competitor path, but a crash, disk error, or registry-write failure can then block that widget name indefinitely and force manual state-directory surgery. Preserve the no-clobber guarantee while recording an authoritative failed-install state and exposing a safe retry or cleanup path, preferably through the plugin doctor contract or another operator-visible recovery flow.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.74

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 370b5150c259.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority Workspaces feature with meaningful user value and bounded but substantial recovery, product, and security review needs.
  • merge-risk: 🚨 compatibility: The PR creates permanent plugin configuration and public plugin-SDK surface whose upgrade and ownership contracts require review.
  • merge-risk: 🚨 security-boundary: The PR enables Gateway-originated third-party fetches and filesystem staging of untrusted widget bundles behind new policy code.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR supplies automated tests, type and lint checks, API-baseline output, and dependency evidence only; add redacted current-head screenshots, a recording, terminal live output, or logs showing full-bleed plus gallery browse, install, pending, and no-auto-mount behavior. Updating the PR body should trigger review, or a maintainer can request @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +702, Tests +837, Docs +47, Generated 0, Other -1. Total +1585 across 29 files.

View PR surface stats
Area Files Added Removed Net
Source 16 745 43 +702
Tests 8 840 3 +837
Docs 2 47 0 +47
Config 0 0 0 0
Generated 1 2 2 0
Other 2 1 2 -1
Total 29 1635 50 +1585

Security concerns:

  • [medium] Retained failed installs lack trusted recovery — extensions/workspaces/src/gallery.ts:388
    Fail-closed retention protects against deleting a path whose ownership became ambiguous, but without an authoritative failed-install record and safe cleanup or retry owner it leaves operators to manipulate security-sensitive state manually.
    Confidence: 0.88

What I checked:

  • Current-head scope: The six-commit head focuses on full-bleed layout, guarded gallery retrieval and installation, shared installation locking, redirect validation, configuration, documentation, and tests. (extensions/workspaces/src/gallery.ts:1, a6749eb96293)
  • Prior-review continuity: The current file list no longer changes the store, widget HTTP response, manifest-entrypoint, or root-carve surfaces behind four previous findings; the earlier installation-recovery concern remains relevant to the rewritten gallery lifecycle. (extensions/workspaces/src/gallery.ts:388, a6749eb96293)
  • New configuration contract: The plugin adds an optional gallery.allowedOrigins array for exact HTTPS origins, with gallery access disabled when it is not configured. (extensions/workspaces/openclaw.plugin.json:15, a6749eb96293)
  • New public SDK contract: The branch publishes guarded-fetch option, redirect, and result types through the public SSRF runtime barrel. (src/plugin-sdk/ssrf-runtime.ts:19, a6749eb96293)
  • Redirect hardening: Each redirect target is synchronously validated before being followed, with tests covering rejection before another request and mutation isolation for callback URL values. (src/infra/net/fetch-guard.ts:683, a6749eb96293)
  • Automated validation: The PR reports focused gallery, Workspaces UI, SSRF, type, lint, API-baseline, and dependency validation on the final head, and the supplied check summary is broadly green apart from the lint aggregator. (extensions/workspaces/src/gallery.test.ts:1, a6749eb96293)

Likely related people:

  • 100yenadmin: The contributor also owns prior merged Workspaces foundation work referenced as pull request 104139, and authored the current apps-layer commits across the central Workspaces and UI paths. (role: feature owner and recent area contributor; confidence: high; commits: 1a1b73cbee0d, 1fc884173310, 9a468879429d; files: extensions/workspaces/src/gallery.ts, extensions/workspaces/src/schema.ts, ui/src/pages/plugin/workspace-view.ts)
  • steipete: The unresolved choice spans OpenClaw product direction, operator configuration, a security-sensitive Gateway network policy, and public plugin-SDK ownership; exact file-level provenance was unavailable in this run. (role: likely product and core API decision owner; confidence: low; files: src/infra/net/fetch-guard.ts, src/plugin-sdk/ssrf-runtime.ts, extensions/workspaces/openclaw.plugin.json)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-07T23:36:33.478Z sha f1ef6a0 :: needs real behavior proof before merge. :: [P2] Make widget install placement recoverable | [P1] Move dashboard runtime state into the canonical store
  • reviewed 2026-07-07T23:46:43.102Z sha 0da800f :: needs real behavior proof before merge. :: [P1] Move dashboard runtime state into the canonical store | [P2] Make widget install placement recoverable | [P2] Use the approved widget manifest entrypoint | [P2] Apply widget CSP on handled 404 responses | [P3] Remove the root carve spec artifact
  • reviewed 2026-07-08T04:31:43.024Z sha 0da800f :: needs real behavior proof before merge. :: [P1] Persist dashboard state in SQLite-backed plugin state | [P2] Make gallery install placement recoverable | [P2] Use the approved widget manifest entrypoint | [P2] Send widget CSP on handled 404 responses | [P3] Remove the root carve spec artifact
  • reviewed 2026-07-10T07:13:38.484Z sha 86c73d7 :: needs real behavior proof before merge. :: [P1] Persist dashboard runtime state in SQLite | [P2] Make gallery installation recoverable | [P2] Mount the approved manifest entrypoint | [P2] Apply widget CSP on handled 404 responses | [P3] Remove the root carve specification

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 7, 2026
@100yenadmin
100yenadmin force-pushed the feat/dashboard-apps-layer branch from 86c73d7 to 117c00a Compare July 13, 2026 12:01
@100yenadmin 100yenadmin changed the title Dashboard: apps layer — full-bleed tabs + widget gallery Workspaces: add full-bleed apps and guarded gallery installs Jul 13, 2026
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation scripts Repository scripts plugin: workspaces Agent-composable Workspaces plugin labels Jul 13, 2026
@100yenadmin
100yenadmin force-pushed the feat/dashboard-apps-layer branch from 117c00a to a6749eb Compare July 13, 2026 12:18
@github-actions github-actions Bot removed the dependencies-changed PR changes dependency-related files label Jul 13, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 13, 2026
@steipete

Copy link
Copy Markdown
Contributor

AI-assisted (approved by Peter)

The full-bleed single-widget tab portion landed separately in #109627, with contributor credit to @100yenadmin preserved. The gallery remains under review as a separate product decision; this PR stays open for that review.

@steipete

Copy link
Copy Markdown
Contributor

AI-assisted (approved by Peter)

Thanks Andy — closing the remaining (gallery) half of this PR, and want to be precise about why, because it's a "not now" rather than a "no":

  • The full-bleed tabs half already landed with your credit in feat(workspaces): add full-bleed single-widget tabs #109627.
  • Workspaces just shipped; we want real experience with how people actually use it before investing in a distribution system. The core model is that the agent writes widgets on demand — we want to see how far that carries.
  • Remote install of runnable widget bundles reopens the whole trust-boundary question (origin trust, integrity, update policy, recovery). That's a can of worms we'd want to open deliberately, likely through the existing ClawHub/plugin distribution machinery rather than a parallel downloader.
  • In the meantime, sharing a custom widget works fine manually — the bundle is just JSON/HTML someone can send to a friend and approve locally.

What would change this: custom widgets becoming visibly popular (people actually sharing them by hand) — that's the signal that a first-class distribution path earns its complexity. Your implementation here will be a great reference when that day comes. Thanks again for the substantial work across this whole stack.

@steipete steipete closed this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. plugin: workspaces Agent-composable Workspaces plugin rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. scripts Repository scripts size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: full-bleed tab layout + "tab app" bundle

2 participants