Skip to content

Backport epic: downstream fixes + features from OpenClaw Workspaces and the Hermes plugin #77

Description

@100yenadmin

Boardstate's downstream deployments evolved after extraction: OpenClaw's in-tree Workspaces gained post-vendoring PRs (#101792 charts, #101354 secure preview, #101826 agent status + decisions, #109627 full-bleed tabs, community fix #108204) and the Hermes plugin shipped v1.0→v1.4 (operational-layer hardening + fixes). A systematic audit (every downstream change classified against library source; each backport claim independently adversarially verified with file:line citations) found 21 confirmed backports. This epic tracks them.

Security / trust boundary

  • S1 — Secret redaction on agent-facing connector errors. BrokerToolError and connection errors propagate raw error.message (packages/broker/src/broker.ts:295, :239); spawn/HTTP failures embed commands/URLs. Port the Hermes plugin's redaction (config command/url/args/env values + nonce, longest-first, length-agnostic) into the broker error path.
  • S2 — Invoke-time manifest-hash re-check on the direct readOnly path. The AND-gate runs at assembly time only (packages/server/src/broker-agent-tools.ts:236); a connector can swap a tool between assembly and execute. Re-verify the grant's toolsHash at invoke time on the direct-read path (mutations already re-check in the engine).
  • S3 — Pin + size-cap custom-widget code at approval. Approval doesn't snapshot/pin what was reviewed and has no size cap (TOCTOU / OOM).
  • S4 — workspace_replace can mint a fabricated pending registry entry for a name that was never scaffolded; validate registry entries against known scaffolds/installs.
  • S5 — Bounded chart point count. No cap anywhere in the chart pipeline; agent-authored data can exhaust the renderer. (OpenClaw caps at 500 — openclaw#101792.)
  • S6 — Review: custom-widget manifest binding scope. OpenClaw narrowed manifests to static-only bindings; the library still allows allowlisted rpc/jailed-file bindings from manifests. Decide + document the intended trust posture.

Correctness

  • B1 — Overlapping-reload stale-clobber race in loadWorkspace (no ordering guard in packages/host/src/store.ts). Same race fixed downstream by community PR openclaw#108204 — port the newest-wins guard.
  • B2 — nearestFreeSlot can return an out-of-range y that schema validation then rejects (packages/core/src/grid.ts).
  • B3 — Bar/gauge axis doesn't force-include zero — bars are measured from the series minimum, misrepresenting magnitude.
  • B4 — Distinguishable error state for malformed chart input. normalizeSeries/resolveType silently coerce bad input to defaults (packages/core/src/transforms/chart.ts:43-64); port OC's 3-state model (empty/error/ready) + role="status" invalid placeholder + i18n key (openclaw#101792).
  • B5 — Re-register connector grants after a doc replace wipes capabilitiesRegistry. The wipe is legitimate document semantics, but nothing re-registers the connector-config-declared grants as requested afterward (the Hermes plugin needed a re-registration listener; template applies hit this).
  • B6 — Validate pending-action timeout config (positive, finite; fail safe on garbage).
  • B7 — Schema guard: at most one widget when layout: "full" is absent from validateTab.
  • B8 — Duplicate-decision guard + reconcile-on-reload for widget approve/reject (openclaw#101826).
  • B9 — Chart aria-label || fallback can emit an empty label (use ?? + real fallback).

Features / parity

  • F1 — Chart props.min/props.max + numerically-stable degenerate/extreme-range handling (library yScale can hit Infinity at extreme finite values) — openclaw#101792.
  • F2 — Binding-driven preview URL (bindings.value precedence over props.url) — openclaw#101354.
  • F3 — Permission gate + "permission required" affordance on decision controls — openclaw#101826.
  • F4 — Preview toolbar a11y: aria-pressed/aria-label/:focus-visible parity with the library's other pressed-state buttons.
  • F5 — Chart aria-label reports observed point count/range, not just the title.
  • F6 — CLI: dashboard tabs full/grid layout-toggle verbs (the schema + view already ship full-bleed).
  • F7 — Cross-process single-writer guard for a shared state dir (two hosts/CLIs on one BOARDSTATE_STATE_DIR double-write today; the Hermes plugin's port-file adoption pattern is the reference).
  • F8 — Fix the OfficeCLI docs/demo tool contract. docs/connectors/officecli.md + examples/operational-demo/fake-officecli.mjs model fictional tools (read_workbook/generate_document); the real officecli mcp exposes a single officecli tool taking {command}. Align docs + fixture (the Hermes plugin hit exactly this).

Verified NOT needing backport

Already upstream (often richer than downstream): full-bleed single-widget tabs; builtin:agent-status; the pending-approval queue/decision flow; sparkline + detail mode (OC's vendored sparkline is a no-op fall-through — the library is ahead there); preview core (URL gate/sandbox/viewports); event-driven binding invalidation. Platform-specific by design: Hermes' color(srgb) token mapping, operator-secret split, embed-policy wiring, tokenized asset route; OC's sandbox-ceiling tier, gateway RPC params. OC's six post-vendoring refactor/tooling commits contain no hidden behavior fixes.

Suggested trains: T1 security (S1-S6), T2 correctness (B1-B9), T3 parity (F1-F8) — one changeset release each.

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-layerThe v2 agent layer (chat, providers, app)mcpThe @boardstate/mcp serverroadmapAct-2 roadmap phasesecurityTouches a SPEC §11 invariant (public-safe only)widgetBuiltin or custom widget work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions