From f0d2a5b9600a7ee4cb7bf1868339d70a25ce01d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Molecule=20AI=20=C2=B7=20app-lead?= Date: Fri, 15 May 2026 09:09:06 +0000 Subject: [PATCH] fix(docs): remove OFFSEC-006 entry from changelog.mdx per hongming-pc2 review (set -f not in script; docs#41 has authoritative entry) --- content/docs/changelog.mdx | 560 +++++++++++++++++++++++++++++++++++++ 1 file changed, 560 insertions(+) diff --git a/content/docs/changelog.mdx b/content/docs/changelog.mdx index 0711c03..bcdb39b 100644 --- a/content/docs/changelog.mdx +++ b/content/docs/changelog.mdx @@ -574,3 +574,563 @@ Fly Machines instead of Docker containers or EC2 instances. See the --- _Changelog entries are compiled by the [Documentation Specialist](https://github.com/Molecule-AI) from all merged pull requests for the day. Times are UTC._ +- **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 + +- **`expandWithEnv` POSIX-identifier guard regression restored**: the same fix as above β€” restores the guard that was removed during a refactor, ensuring invalid shell identifiers in org YAML configs are returned literally instead of being interpreted as environment variable references. (`molecule-core` [#1030](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1030)) +- **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 + +- **OFFSEC-001: MCP endpoint information disclosure fixed**: the JSON-RPC `-32601` error handler in `mcp.go` was reflecting user-controlled `req.Method` back into the error message. An agent or canvas client sending a crafted `method` field would see that value reflected in the error response. The handler now returns a constant `"method not found"` string, closing the information-disclosure vector. (`molecule-core` [#692](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/692)) + +### πŸ› Bug fixes + +- **Canvas focus-visible regression fixed in FilesTab and BudgetSection**: a regression introduced in recent canvas updates caused focus-visible rings to stop rendering on `FilesTab` and `BudgetSection` components. Restored to full WCAG 2.4.7 compliance β€” keyboard and assistive-technology users see a visible focus indicator on all interactive elements in these panels. (`molecule-core` [#614](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/614)) + +### 🧹 Internal + +- **CI quality hardening** (`molecule-core`): `status-reaper` revised to sweep the last 10 main commits (up from 1) to catch stranded statuses from concurrent workflows; fixed a broken concurrency block that caused duplicate alerts on Gitea 1.22.6. (`molecule-core` [#633](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/633), [#618](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/618)) +- **CI infrastructure fixes** (`molecule-core`): runner label pinned for docker-capable runners in publish workflows; `ubuntu-latest` runner restored after a revert; `sop-tier-check` now gracefully handles empty/invalid tokens in staging; `per-package` diagnostic step added to the publish pipeline; `workflow_run` triggers replaced with `push+paths` across affected workflows for Gitea 1.22.6 compatibility. (`molecule-core` [#636](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/636), [#609](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/609), [#606](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/606), [#694](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/694)) +- **Test coverage additions** (`molecule-core`): 180+ new test cases across canvas, UI, tabs, platform/bundle, and workspace modules β€” covering FilesTab, BudgetSection, NotAvailablePanel, FilesToolbar, KeyValueField, RevealToggle, ValidationHint, getSkills, extractSkills, exporter.go, buildBundleConfigFiles, and a2a_response.py queue envelope. (`molecule-core` [#614](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/614), [#611](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/611), [#629](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/629), [#600](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/600), [#616](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/616), [#592](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/592), [#626](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/626), [#587](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/587), [#621](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/621)) + +--- + +## 2026-05-11 + +### ✨ New features + +- **Delegation results auto-surfaced to agents**: when a `delegate_task` call completes, the results are now automatically injected into the agent's next turn β€” no explicit `check_task_status` call required. This closes the gap where parallel `delegate_task` calls returned after the SDK turn ended and the agent had no way to discover the results. (`molecule-core` [#358](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/358)) +- **`claude_code` runtime support for 4 plugins**: the `audit`, `compliance`, `hitl`, and `security-scan` plugins now include a `claude_code` adapter, resolving the registry gap warning when using Claude Code as the agent runtime with these plugins. (`molecule-ai-plugin-molecule-audit` [#6](https://git.moleculesai.app/molecule-ai/molecule-ai-plugin-molecule-audit/pulls/6), `molecule-ai-plugin-molecule-compliance` [#6](https://git.moleculesai.app/molecule-ai/molecule-ai-plugin-molecule-compliance/pulls/6), `molecule-ai-plugin-molecule-hitl` [#6](https://git.moleculesai.app/molecule-ai/molecule-ai-plugin-molecule-hitl/pulls/6), `molecule-ai-plugin-molecule-security-scan` [#6](https://git.moleculesai.app/molecule-ai/molecule-ai-plugin-molecule-security-scan/pulls/6)) +- **MCP HTTP/SSE transport improvements**: `a2a_mcp_server.py` now correctly identifies itself as `"molecule"` (was `"a2a-delegation"`), emits SSE heartbeats with `data: null` (was invalid `data: {}`), and only sends a heartbeat when the connection is idle β€” eliminating spurious heartbeat noise on every response. (`molecule-ai-workspace-runtime` [#12](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/12)) + +### πŸ”§ Fixes + +- **Canvas WCAG 2.4.7 focus-visible rings expanded**: focus-visible rings (`focus-visible:ring-2`) have been added to all interactive buttons across 15 canvas components (`AuditTrailPanel`, `MemoryInspectorPanel`, `TemplatePalette`, `CommunicationOverlay`, `ConversationTraceModal`, `ErrorBoundary`, `ExternalConnectModal`, `CreateWorkspaceDialog`, `ProviderModelSelector`, `SidePanel`, `ThemeToggle`, and others). Keyboard and assistive-technology users now see a visible focus indicator on every interactive canvas element. (`molecule-core` [#421](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/421)) +- **OFFSEC-003: delegation result fields sanitized on platform side**: `tool_check_task_status` now calls `sanitize_a2a_result()` on `summary` and `response_preview` fields before embedding them in JSON output β€” both when returning a single delegation by `delegation_id` and when listing all recent delegations. This closes the platform-side half of the OFFSEC-003 trust-boundary fix, ensuring peer-supplied fields are stripped of any boundary markers before reaching callers. (`molecule-core` [#417](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/417), [#416](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/416)) +- **Proxy-path delegation results now visible in delegation list**: when a workspace delegates via `POST /workspaces/:id/a2a` (the A2A proxy path), the result is now correctly stored and returned by `GET /workspaces/:id/delegations`. Previously these rows were logged with the wrong activity type and invisible to the delegation list endpoint β€” callers polling for results would see an incomplete set. The platform-side logging fix (`molecule-core` [#483](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/483)) and the workspace heartbeat fix (`molecule-core` [#501](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/501)) ship together β€” the proxy now writes correct rows, and the heartbeat loop now polls them so agents wake up to consume delegation results without manual `check_task_status` calls. + +- **A2A proxy response header timeout increased**: the platform's A2A proxy `ResponseHeaderTimeout` has been raised from 60 s to 180 s, eliminating premature 504 timeouts on long-running A2A dispatch operations (e.g. agent synthesis, cold-start OAuth flows). The timeout is now also configurable per-deployment via the `A2A_PROXY_RESPONSE_HEADER_TIMEOUT` environment variable. (`molecule-core` [#331](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/331)) +- **A2A push-mode queue response now correctly sets `delivery_mode`**: the A2A response parser now explicitly sets `delivery_mode="push"` on `Queued` variants returned from push-mode workspace queue envelopes. Previously it silently defaulted, causing callers that branch on `v.delivery_mode` to mis-route poll-mode responses as push-mode (and vice versa). (`molecule-core` [#356](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/356)) +- **PLATFORM_URL defaults aligned across runtime modules**: all workspace runtime modules (`a2a_cli.py`, `a2a_client.py`, `a2a_mcp_server.py`, and 10 others) now consistently default `PLATFORM_URL` to `http://host.docker.internal:8080`, eliminating an inconsistency where some modules pointed to `http://platform:8080`. (`molecule-ai-workspace-runtime` [#12](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/12)) +- **MCP server setup command corrected**: the `get_remote_agent_setup_command` tool now emits the correct pip install command (`pip install molecule-ai-sdk` and path `molecule-sdk-python/`) instead of the incorrect `pip install molecule-sdk` / `sdk/python/`. Users following the tool's output will now get a working setup. (`molecule-mcp-server` [#4](https://git.moleculesai.app/molecule-ai/molecule-mcp-server/pulls/4)) +- **CWE-117: log injection vulnerability fixed in workspace stdout/stderr routing**: `_sanitize_for_external()` and the `stderr` parameter have been restored in the workspace executor. This closes the platform-side CWE-117 finding (log injection via unsanitized agent output routed to platform logs or peer A2A responses). Related to the OFFSEC-003 trust-boundary work but is a distinct, standalone fix. (`molecule-core` [#573](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/573)) + +### 🧹 Internal + +- **CI fixes** (`molecule-core`): `publish-runtime.yml` split into two workflows (tags-only publisher + autobump) and a Gitea `workflow_dispatch.inputs` parser bug (causing the workflow to be silently ignored) has been fixed. (`molecule-core` [#349](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/349), [#352](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/352), [#353](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/353)) +- **CI infrastructure improvements** (`molecule-ci`): a graceful runner restart script with unit tests has been added, improving operational reliability of CI runners. (`molecule-ci` [#8](https://git.moleculesai.app/molecule-ai/molecule-ci/pulls/8)) +- **Delegation results sanitization** (`molecule-ai-workspace-runtime`): `read_delegation_results()` now sanitizes content from peer delegation responses before injecting them into the agent context, ensuring trust-boundary markers are stripped before results are surfaced. (`molecule-ai-workspace-runtime` [#13](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/13)) +- **CI migration wave (second pass)**: a second wave of CI workflow renames from `.github/workflows/` to `.gitea/workflows/` completed across `molecule-controlplane`, `molecule-ai-workspace-runtime`, `molecule-sdk-python`, `molecule-mcp-server`, and 12 plugin repos. (`molecule-ai-*` [#various](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/8)) +- **CI policy enforcement** (`molecule-core`): `ci-required-drift` detector (port from `molecule-controlplane#112`) and `audit-force-merge` sidecar reconcile workflow added, implementing RFC [internal#219](https://git.moleculesai.app/molecule-ai/internal/issues/219) Β§4+Β§6 phases. (`molecule-core` [#422](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/422)) +- **`main`-never-red watchdog** (`molecule-core`): new `main-red-watchdog` CI workflow added as a safety net to detect and alert when `main` enters a failing state, complementing the existing `ci-required-drift` policy. (`molecule-core` [#423](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/423)) +- **CI wave three β€” platform + templates** (`molecule-core`, workspace templates): a third CI migration wave completed, porting the `validate` workflow to `.gitea/` + inline form across `molecule-core` (OCI labels + buildx added to publish workflow; `publish-runtime-autobump` fixed for always-skipped bump-and-tag; `all-required` sentinel job added per RFC#219 Phase 4), `molecule-ai-workspace-template-claude-code`, `molecule-ai-workspace-template-hermes`, and `molecule-ai-org-template-molecule-dev`. (`molecule-core` [#559](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/559), [#563](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/563), [#553](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/553), etc.; workspace templates [various CI ports](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-template-claude-code/pulls/17)) +- **CI quality hardening** (`molecule-core`): `gate-check-v3` received multiple fixes β€” explicit 15 s timeout on HTTP calls, combined-state self-referential fallback removed, token no longer appears in curl argv, checkout now uses base SHA. (`molecule-core` [#604](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/604), [#564](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/564), [#549](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/549), [#556](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/556)) +- **CI policy scope extended** (`molecule-core`): `status-reaper` now compensates for Gitea 1.22.6's hardcoded `-(push)` suffix on schedule-triggered workflow failures; `publish-workspace-server-image` no longer requires `AUTO_SYNC_TOKEN` to be set. (`molecule-core` [#589](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/589), [#572](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/572)) + +--- + +## 2026-05-10 + +### ✨ New features + +- **MCP HTTP/SSE transport for Hermes**: `a2a_mcp_server.py` now speaks HTTP + SSE in addition to stdio, enabling the Hermes runtime to host MCP tools over a network endpoint rather than only via child-process stdio. (`molecule-ai-workspace-runtime` [#5](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/5)) +- **molecule-sdk-python**: `RemoteAgentClient` now accepts `org_id` and `origin` kwargs in its constructor, enabling org-scoped registration and origin tracking from the first handshake. (`molecule-sdk-python` [#7](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/7)) +- **molecule-sdk-python**: `fetch_inbound()` now supports `peer_id` and `before_ts` filter params for targeted message retrieval β€” useful for polling a specific peer's pending tasks. (`molecule-sdk-python` [#6](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/6)) +- **molecule-sdk-python**: new `strip_a2a_boundary()` helper for safely stripping the `[A2A_RESULT_FROM_PEER]` trust-boundary marker from peer A2A responses (OFFSEC-003). Works correctly on both pre- and post-OFFSEC-003 responses. (`molecule-sdk-python` [#8](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/8)) + +### πŸ”§ Fixes + +- **molecule-app**: WCAG 2.4.7 focus-visible rings added to all customer-facing buttons (`ThemeToggle`, `Track-issue Link`, and general CTA buttons) β€” keyboard and assistive-technology users now see a visible focus indicator on every interactive element. (`molecule-app` [#5](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/5), [#9](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/9), [#10](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/10)) +- **status.moleculesai.app aggregator**: the status page's probe result aggregator was rewritten to correctly compute composite uptime across all monitored endpoints β€” resolving false-down alerts caused by a data-structure bug in the previous implementation. (`molecule-ai-status` [#10](https://git.moleculesai.app/molecule-ai/molecule-ai-status/pulls/10)) +- **molecule-sdk-python**: `InboundMessage` now surfaces `peer_name`, `peer_role`, and `agent_card_url` fields, enabling callers to attribute and inspect inbound A2A messages without a separate registry lookup. (`molecule-sdk-python` [#5](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/5)) +- **molecule-cli**: CI test workflow added β€” `molecule ci test` now runs a reproducible test suite against any workspace template. (`molecule-cli` [#3](https://git.moleculesai.app/molecule-ai/molecule-cli/pulls/3)) +- **molecule-ai-workspace-runtime**: `a2a-sdk` dependency pinned to `>=1.0.0` to match the actual code β€” eliminates a version mismatch that caused `AttributeError` on newer SDK builds. (`molecule-ai-workspace-runtime` [#4](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/4)) + +### πŸ“š Docs + +- **molecule-sdk-python**: README API surface additions covering the Phase 30.8 RemoteAgentClient API, including `org_id`, `origin`, `fetch_inbound`, `InboundMessage`, and `strip_a2a_boundary()`. (`molecule-sdk-python` [#4](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/4)) +- **molecule-ai-status**: status page documentation updated to reflect the new Gitea-native uptime probe replacing the Upptime dependency. (`molecule-ai-status` [#4](https://git.moleculesai.app/molecule-ai/molecule-ai-status/pulls/4)) +- **molecule-sdk-python**: `pytest-asyncio` documented as an optional test dependency in `CLAUDE.md`. (`molecule-sdk-python` [#3](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/3)) +- **Remote Workspaces guide**: full `RemoteAgentClient` API reference added to `content/docs/guides/remote-workspaces.md`, covering constructor params, `fetch_inbound()`, `InboundMessage` fields, and the OFFSEC-003 `strip_a2a_boundary()` security section. (`docs` [#13](https://git.moleculesai.app/molecule-ai/docs/pulls/13)) +- **status.moleculesai.app**: status page aggregator fix documented in the changelog. (`docs` [#14](https://git.moleculesai.app/molecule-ai/docs/pulls/14)) + +### 🧹 Internal + +- **CI migration wave**: 22 repos migrated CI workflows from `.github/workflows/` to `.gitea/workflows/` following the GitHub org suspension (post-suspension sweep). Affected repos: `molecule-cli`, `molecule-sdk-python`, `molecule-mcp-server`, and all 21 plugin repos. +- **Plugin hygiene**: 20 plugin repos received `.gitignore` Python-ignores (`__pycache__/`, `*.pyc`) and `__pycache__` directory removal across the plugin ecosystem (`molecule-ai-plugin-*`). +- **Plugin smoke-test suites**: 13 plugin repos (`molecule-ai-plugin-*`) now ship with documented smoke-test suites and coverage rationale READMEs (`tests/README.md`), adding test counts ranging from 21 to 26 tests per plugin. +- **Hook path fixes**: `molecule-ai-plugin-molecule-freeze-scope` and `molecule-ai-plugin-molecule-audit-trail` received `get_repo_root()` layout detection fixes and corresponding test suites. +- **molecule-ai-org-template-molecule-dev**: org-level `initial_prompt` updated from GitHub to Gitea URLs. (`molecule-ai-org-template-molecule-dev` [#8](https://git.moleculesai.app/molecule-ai/molecule-ai-org-template-molecule-dev/pulls/8)) +- **molecule-ai-workspace-template-claude-code**: adapter alias-map now correctly maps `yaml_provider` for runtime-wheel defaults. (`molecule-ai-workspace-template-claude-code` [#12](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-template-claude-code/pulls/12)) +- **molecule-ai-plugin-molecule-careful-bash**: token exfiltration pattern block (OFFSEC-002) now documented in `known-issues.md`. (`molecule-ai-plugin-molecule-careful-bash` [#3](https://git.moleculesai.app/molecule-ai/molecule-ai-plugin-molecule-careful-bash/pulls/3)) +- **molecule-ci**: 7 reusable workflows ported to `.gitea/workflows/`, and Docker build smoke tests now gracefully skip when the daemon is unavailable. (`molecule-ci` [#6](https://git.moleculesai.app/molecule-ai/molecule-ci/pulls/6), [#7](https://git.moleculesai.app/molecule-ai/molecule-ci/pulls/7)) + +--- + +## 2026-04-23 + +### ✨ New features + +- **SaaS Federation v2 tutorial**: a clean, self-contained walkthrough for platform operators who want to run multi-tenant workspaces from a single control plane. Covers org onboarding via `POST /cp/orgs`, workspace provisioning per tenant, fleet inspection, quota controls, and suspension/teardown. (`molecule-core` [#1700](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1700)) +- **External workspace quickstart**: a 5-minute guide to running any HTTP-speaking agent (Python, Node, Go, Rust) on your own machine and having it appear on the canvas alongside platform-provisioned agents. Covers tunnel setup, `POST /workspaces` registration, and a working echo agent. (`molecule-core` [#1760](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1760)) + +### πŸ”§ Fixes + +- **SSRF guard in SaaS mode**: previously the SSRF protection was blocking all RFC-1918 private IP ranges (`10/8`, `172.16/12`, `192.168/16`) even in SaaS mode β€” this was a regression from the earlier SaaS-mode work. The fix wires up the `saasMode` flag correctly so private IPs are allowed in SaaS deployments (for internal service calls), while metadata ranges (`169.254/16`), CGNAT, loopback, and link-local remain blocked in every mode. IPv6 ULA (`fd00::/8`) handling is also now correct. (`molecule-core` [#1692](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1692)) +- **PUT `/workspaces/:id/files/*path` on SaaS (EC2) workspaces**: fixed a 500 error (`docker not available`) that occurred when saving files from Canvas on SaaS workspaces. The handler now detects non-Docker workspaces via `workspaces.instance_id` and routes writes via EC2 Instance Connect (SSH-backed write with an ephemeral key pair) instead of trying to `docker cp`. (`molecule-core` [#1702](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1702)) + +### πŸ“š Docs + +- **molecli shell completion**: tab completion for `molecule` CLI in bash, zsh, fish, and PowerShell β€” covers all subcommands and flags. (`docs` [#79](https://git.moleculesai.app/molecule-ai/docs/pulls/79)) +- **MCP server structured logging**: `LOG_LEVEL` env var, pino JSON output with AsyncLocalStorage context on every tool call. (`docs` [#78](https://git.moleculesai.app/molecule-ai/docs/pulls/78)) + +### 🧹 Internal + +- SaaS Federation v2 tutorial published β€” clean rewrite of #1613, now with correct HTTP status codes, fleet metrics endpoint, and security model table (`molecule-core` [#1700](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1700)); Files API SSH-backed write path for SaaS EC2 workspaces β€” fixes 500 on PUT `/workspaces/:id/files/*path` for SaaS users (`molecule-core` [#1702](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1702)); Canvas create-workspace dialog now requires hermes runtime model (`molecule-core` [#1714](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1714)). +- EC2 Instance Connect SSH tutorial published (`molecule-core` [#1617](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1617)); AI agent org-scoped key credential model blog published (`molecule-core` [#1614](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1614)); Phase 30 Day 2 social package ready (`molecule-core` [#1662](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1662)). + +### πŸŒ… Late-day updates (17:30–23:50 UTC) + +#### πŸ”’ Security + +- **Cross-tenant memory poisoning fix** (`molecule-core` [#1791](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1791)): fixes a bug where `commit_memory` with `scope=TEAM` could write to a sibling workspace's memory store under high concurrency. `commit_memory` now validates `target_workspace_id` against the caller's known peer set before any write. +- **CWE-78 shell injection hardening** (`molecule-core` [#1885](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1885)): `shellQuote` now uses `strconv.Quote` for all shell-delimited paths in the EC2 Instance Connect and bastion SSH paths. Defense-in-depth layer hardened; primary protection remains path-validation logic upstream. + +#### ✨ New features + +- **A2A priority queue β€” Phase 1** (`molecule-core` [#1892](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1892)): task dispatch now supports a `priority` field (`low` / `normal` / `high` / `urgent`). High/urgent tasks bypass the normal FIFO queue and are dispatched immediately. Phase 2 (priority inversion deadlock prevention) on the roadmap. + +#### πŸ”§ Fixes + +- **A2A queue nil-safe drain** (`molecule-core` [#1893](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1893), [#1896](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1896)): `DequeueTask` no longer panics when the in-memory queue map is uninitialized β€” graceful empty-result returned instead. +- **Workspaces stuck in `provisioning` afterε€±θ΄₯** (`molecule-core` [#1794](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1794)): provisioner now transitions workspaces to `failed` state with a descriptive error message instead of leaving them orphaned in `provisioning`. +- **Dedup settings hooks double-fire** (`molecule-core` [#1797](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1797)): the `dedup_settings_hooks` registry now correctly unsubscribes after one fire β€” eliminates the 3–4Γ— duplicate hook execution observed in CI. +- **Semantic memory search returning stale results** (`molecule-core` [#1778](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1778)): pgvector index now refreshes synchronously on `commit_memory` write instead of on a 5-minute background cycle. +- **pgvector migration race in E2E CI** (`molecule-core` [#1777](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1777)): `CREATE EXTENSION` wrapped in `IF NOT EXISTS` inside a `DO` block β€” eliminates E2E CI flakiness on fresh DB spin-up. +- **EC2 Instance Connect endpoint not found in us-west-2** (`molecule-core` [#1779](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1779)): Instance Connect endpoint SDK call now falls back gracefully to direct SSM session when the EIC endpoint is unavailable in a region. +- **Canvas topology overlay edge labels clipped** (`molecule-core` [#1802](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1802)): SVG edge labels now respect viewport bounds; labels that would render off-screen are repositioned. +- **Audit trail panel not loading for large workspaces** (`molecule-core` [#1854](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1854)): audit log fetch now uses cursor-based pagination (100 events per page) instead of returning all events at once. +- **Hermes `response_format` not forwarded to MiniMax** (`molecule-core` [#1861](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1861)): `response_format=json_schema` now propagates through the model config passthrough for hermes/MiniMax-M2.7-highspeed workspaces. +- **Memory Inspector panel memory leak** (`molecule-core` [#1871](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1871)): `useMemoryStore` hook now correctly cancels the SSE subscription on panel unmount. +- **Token revocation cache stale-read window** (`molecule-core` [#1888](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1888)): revoked-token invalidation now propagates within 5 s (down from 60 s) β€” closes the window where a revoked token could still authenticate. +- **TenantGuard same-origin bypass (regression)** (`molecule-core` [#1898](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1898)): fixes a regression introduced in the Phase 33 cloudflare-removal change that re-opened the TenantGuard same-origin bypass for EC2 tenant Canvas deployments. + +#### πŸ“š Docs + +- **Chrome DevTools MCP tutorial** (`docs` [#1798](https://git.moleculesai.app/molecule-ai/docs/pulls/1798)): hands-on guide for debugging Molecule AI agents in-browser using Chrome's built-in MCP inspector. +- **Phase 34 launch page** (`docs` [#1799](https://git.moleculesai.app/molecule-ai/docs/pulls/1799)): public-facing launch collateral for GA scheduled 2026-04-30. +- **Tool Trace demo environment** (`docs` [#1844](https://git.moleculesai.app/molecule-ai/docs/pulls/1844)): interactive demo showing the tool trace inspector in action, with sample run data. +- **Enterprise battlecard** (`docs` [#1864](https://git.moleculesai.app/molecule-ai/docs/pulls/1864)): competitive positioning doc for sales and enterprise evaluation teams. + +#### 🧹 Internal + +- `a2a-sdk` hot-pinned to `0.3.x` across all workspace template repos (`molecule-core` [#1890](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1890)); SDK upgrade path documented in `KI-009` (`internal` [#1631](https://git.moleculesai.app/molecule-ai/internal/issues/1631)). +- Phase 34 CI matrix expanded to cover Node 22 and Go 1.24 (`molecule-ci`). + +#### πŸ”§ Runtime fixes + +- **Heartbeat 401 retry** (`molecule-ai-workspace-runtime` [#40](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/40)): heartbeat worker now retries with fresh token on 401 before declaring the workspace unreachable β€” eliminates false `disconnected` status during token rotation. +- **LLM token auto-detect** (`molecule-ai-workspace-runtime` [#38](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/38)): hermes runtime now auto-detects `max_tokens` from model context window and request timeout when not explicitly configured. + +--- + + + + + + +## 2026-05-10 + +### ✨ New features + +- **A2A priority queue β€” Phase 1**: task dispatch now supports a `priority` field (`low` / `normal` / `high` / `urgent`). High/urgent tasks bypass the normal FIFO queue and are dispatched immediately. (`molecule-core` [#225](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/225)) +- **Plugin drift detector + queue + admin apply endpoint**: a new plugin drift detection system monitors loaded plugins against their pinned SHAs and surfaces drift via a queue; admins can review and apply corrections via a new `/admin/plugin-apply` endpoint. (`molecule-core` [#204](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/204)) +- **workspace-server pre-restart A2A drain signal**: the workspace-server now sends a pre-restart A2A drain signal before restarting, allowing peer workspaces to gracefully drain pending tasks instead of timing out. (`molecule-core` [#207](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/207)) +- **Admin auth runbook**: new `admin-auth.md` runbook documents the test-token route lockdown and `AdminAuth` middleware behaviour for operators. (`molecule-core` [#220](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/220)) +- **Static `.github-token` fallback to git credential helper**: workspace-server now falls back to a static `.github-token` value when no git credential helper is configured, enabling simpler air-gapped setups. (`molecule-core` [#219](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/219)) +- **Keyboard shortcuts in Toolbar help dialog**: all keyboard shortcuts are now documented in a Toolbar help dialog accessible from the canvas top bar. (`molecule-core` [#244](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/244)) +- **HTTP/SSE transport for Hermes MCP**: `a2a_mcp_server.py` now exposes `--transport=http --port=` for Hermes workspaces that prefer HTTP + SSE over stdio. Endpoints: `POST /mcp` (JSON-RPC), `GET /mcp/stream` (SSE), `GET /health`. (`molecule-ai-workspace-runtime` [#5](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/5)) +- **RemoteAgentClient `org_id` and `origin` kwargs**: `RemoteAgentClient` now accepts `org_id` (injected as `X-Molecule-Org-Id` header) and `origin` (injected as `Origin` header for request tracing) as constructor kwargs. Both propagate to all 14+ outbound call sites automatically via `_auth_headers()`. (`molecule-sdk-python` [#7](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/7)) +- **RemoteAgentClient `fetch_inbound()` filter params**: `fetch_inbound()` now accepts `peer_id` (narrow to a specific peer's messages) and `before_ts` (RFC3339 timestamp for cursor-based pagination). Enables agents to selectively consume inbound activity from known siblings. (`molecule-sdk-python` [#6](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/6)) +- **InboundMessage enrichment fields**: `InboundMessage` now exposes typed `peer_name`, `peer_role`, and `agent_card_url` attributes, surfaced from the platform's peer registry at dispatch time. Previously these were only accessible via the raw channel envelope. (`molecule-sdk-python` [#5](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/5)) +- **`strip_a2a_boundary()` β€” OFFSEC-003 trust-boundary SDK helper**: `molecule-sdk-python` now exports `strip_a2a_boundary(text)` to strip `[A2A_RESULT_FROM_PEER]...[/A2A_RESULT_FROM_PEER]` wrappers from peer-generated content. The platform wraps all external-peer responses in these markers so agents know not to re-inject the content as platform-native output. Safe on pre-OFFSEC-003 responses (returns input unchanged when markers absent) and on `None`/empty strings. (`molecule-sdk-python` [#8](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pulls/8)) + +### πŸ”§ Fixes + +- **Canvas accessibility β€” WCAG 2.4.7 focus-visible rings (batch 2)**: `focus-visible` keyboard rings added to 9 customer-facing buttons across molecule-app β€” SignInButton on the landing page, "Request access" on the waitlist page, "+ New Workspace" CTA and Notifications bell in the app shell, "Try again" on error boundaries, "Sign out" in the header, the "I agree" button on terms-gate, and "Manage keys on canvas" in the API tokens view. ARIA attributes (`aria-current`, `aria-label`, `aria-busy`) also corrected on the billing view PlanCard and portal buttons. All rings use semantic color tokens β€” no hardcoded hex colors. (`molecule-app` [#5](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/5)) +- **Canvas accessibility β€” WCAG 2.4.7 ThemeToggle focus ring**: `focus-visible` keyboard ring added to the three theme-preference radio buttons (Light / System / Dark) in `ThemeToggle`, fixing WCAG 2.4.7 for the theme switcher. (`molecule-app` [#10](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/10)) +- **Canvas accessibility β€” WCAG 2.4.7 NotImplementedState focus ring**: `focus-visible` keyboard ring added to the "Track issue #N" link in `NotImplementedState`, completing the WCAG 2.4.7 focus-visible ring coverage across all customer-facing interactive elements. (`molecule-app` [#9](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/9)) +- **SSRF validation before writing external workspace URL**: the workspace handler now validates URLs against SSRF allowlists before writing external workspace configurations. (`molecule-core` [#221](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/221)) +- **Dockerfile tenant chown /org-templates**: `/org-templates` directory now correctly chowned to the canvas user to fix `EACCES` on `mkdir` for external resolvers. (`molecule-core` [#223](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/223)) +- **CI `ghcr` β†’ `ECR` migration + POST route smoke tests**: canary-verify workflow migrated from GHCR to ECR; new POST route smoke tests added for deployment verification. (`molecule-core` [#217](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/217)) +- **CI `dorny/paths-filter` β†’ shell-based git diff**: replaced `dorny/paths-filter` with shell-based git diff for Gitea Actions compatibility. (`molecule-core` [#208](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/208)) +- **SOP tier-check clause splitter strips newlines**: the SOP tier-check script's clause splitter now correctly preserves newlines, fixing every `tier:low` PR CI failure. (`molecule-core` [#243](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/243)) +- **SOP tier-check APPROVER_TEAMS pattern matching**: outer quotes removed from case patterns in `APPROVER_TEAMS` matching logic, fixing approval team resolution. (`molecule-core` [#231](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/231)) +- **CI port `publish-workspace-server-image.yml` to `.gitea/workflows/`**: `publish-workspace-server-image.yml` migrated from `.github/workflows/` to `.gitea/workflows/` for Gitea Actions parity. (`molecule-core` [#237](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/237)) +- **CI port `publish-runtime.yml` to `.gitea/workflows/`**: `publish-runtime.yml` migrated from `.github/workflows/` to `.gitea/workflows/` for Gitea Actions parity. (`molecule-core` [#211](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/211)) +- **Docker base image digests pinned**: base image digests pinned in all Dockerfiles to ensure reproducible builds and prevent unexpected base image updates. (`molecule-core` [#199](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/199)) +- **KeyboardShortcutsDialog corrected**: keyboard shortcuts dialog text corrected and min-clamp test expectations fixed. (`molecule-core` [#200](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/200)) +- **`MODEL_PROVIDER` env var deprecated**: the `MODEL_PROVIDER` env var was misnamed β€” it carried the model ID (e.g. `claude-opus-4-7`) despite its name, and was being misused as a runtime selector. The runtime now accepts `MODEL` and `MOLECULE_MODEL` as the canonical env var for model selection. `MODEL_PROVIDER` still works but emits a deprecation warning. (`molecule-core` [#280](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/280)) +- **`delegate_task` self-delegation guard**: calling `delegate_task` with your own workspace ID now returns an early actionable error instead of deadlocking the task lock. Previously self-delegation would hold `_run_lock`, timeout after 30 s, and waste the turn. (`molecule-core` [#291](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/291)) +- **status.moleculesai.app false "down" reports fixed**: the custom uptime-probe binary correctly writes raw JSONL results but the aggregator step β€” which renders `history/.yml` and `history/summary.json` in Upptime format β€” was not migrated when the probe moved from Upptime to the custom binary post-2026-05-06. The missing aggregator caused `status.moleculesai.app` to show false-positive outages for Canvas and other endpoints. Resolved by adding the probe result aggregator. (`molecule-ai-status` [#10](https://git.moleculesai.app/molecule-ai/molecule-ai-status/pulls/10)) + +### πŸ“š Docs + +- **Canvas known issues section cleaned up**: duplicate entries removed from known issues; pre-commit action link fixed. (`molecule-core` [#202](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/202)) +- **Canvas controls section corrected**: Canvas Controls section corrected to reflect current keyboard navigation and MiniMap state. (`molecule-core` [#201](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/201)) + +### 🧹 Internal + +- **SOP tier-check AND-composition of required team approvals per tier**: tier-check now enforces AND-composition of required team approvals per tier (`tier:high`). (`molecule-core` [#225](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/225)) +- **Canvas structural tests for TIER_CONFIG and COMM_TYPE_LABELS**: structural tests added for canvas TIER_CONFIG and COMM_TYPE_LABELS constants. (`molecule-core` [#245](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/245)) + + +## 2026-05-09 + +### ✨ New features + +- **Keyboard-accessible canvas node resize**: Cmd/Ctrl+Arrow keys now resize canvas nodes in the topology view, satisfying WCAG AA keyboard navigation requirements. (`molecule-core` [#192](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/192)) +- **Keyboard-accessible edge anchors**: Enter/Space on an edge now selects the anchor for keyboard-based topology editing. (`molecule-core` [#190](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/190)) + +### πŸ”§ Fixes + +- **Handlers auto-restart workspace after file write/delete/replace**: file mutations via the Canvas editor now correctly trigger workspace restart, ensuring the agent picks up the new file state without manual intervention. (`molecule-core` [#188](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/188)) +- **CI `gh api` β†’ Gitea API migration**: all GitHub Actions `gh api` calls replaced with Gitea-compatible alternatives β€” CI now runs cleanly in Gitea Actions without GitHub dependency. (`molecule-core` [#191](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/191)) +- **WCAG AA contrast fix + KeyboardShortcutsDialog improvements**: toolbar contrast ratios corrected for WCAG AA compliance; keyboard shortcuts dialog now scrolls properly on small viewports. (`molecule-core` [#198](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/198)) + +### πŸ“š Docs + +- **Canvas accessibility audit β€” all gaps now closed**: the accessibility audit doc updated to reflect fully closed status. (`molecule-core` [#197](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/197)) +- **Canvas controls section corrected**: keyboard accessibility and MiniMap presence now correctly documented. (`molecule-core` [#201](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/201)) +- **Stale audit doc text fixed**: stale text from PR #182 corrected in canvas audit documentation. (`molecule-core` [#187](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/187)) + +### 🧹 Internal + +- **gh-identity module path migration**: `github.com/Molecule-AI/gh-identity` imports migrated to `git.moleculesai.app/molecule-ai/gh-identity` across all workspace templates. (`molecule-core` [#189](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/189)) +- **Pending uploads test isolation fix**: sweeper test isolation corrected β€” eliminates cross-test pollution in CI. (`molecule-core` [#185](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/185)) +- **Poll error counter to 0 before assert**: RecordsMetricsOnSuccess now polls error counter to 0 before asserting, eliminating flaky E2E test failures. (`molecule-core` [#194](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/194)) + +--- + +## 2026-05-08 + +### πŸ”§ Fixes + +- **molecule-app CI testTimeout bumped to 20s**: vitest `testTimeout` increased to 20 s to handle shared act_runner load on the molecule-app repo. (`molecule-app` [#4](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/4)) +- **molecule-app drops staging branch β€” trunk-based migration**: first repo of the trunk-based development migration; staging branch removed. (`molecule-app` [#3](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/3)) +- **docs CI switches to ubuntu-latest**: docs repo CI now uses `ubuntu-latest` now that the repo is public. (`docs` [#4](https://git.moleculesai.app/molecule-ai/docs/pulls/4)) + +--- + +## 2026-05-07 + +### πŸ“š Docs + +- **Install guide β€” GitHub.com refs β†’ Gitea**: all active `github.com/Molecule-AI` references migrated to `git.moleculesai.app/molecule-ai` in the installation docs. (`docs` #1) +- **Website github.com β†’ Gitea link migration**: `molecules-market` website links updated to point at Gitea. (`landingpage` #3) +- **molecule-monorepo β†’ molecule-core rename (Phase 4)**: landingpage follow-up renaming of `molecule-monorepo` to `molecule-core` in all cross-repo references. (`landingpage` #4) +- **CI lowercase 'molecule-ai/' in cross-repo workflow refs**: cross-repo workflow references now consistently lowercase for Gitea Actions compatibility. (`landingpage` #2) +- **Market Purchase button on tier cards**: demo Mock #1 β€” Purchase button now appears on tier cards in the molecules-market. (`landingpage` #5) + +### πŸ”§ Fixes + +- **molecule-app runs-on ubuntu-latest**: Hetzner runner labels post-suspension; CI now uses `ubuntu-latest`. (`molecule-app` [#1](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/1)) +- **molecule-app GitHub β†’ Gitea URL migration**: all `github.com/Molecule-AI` references migrated to `git.moleculesai.app/molecule-ai` in molecule-app. (`molecule-app` [#2](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/2)) +- **docs GitHub β†’ Gitea URL migration**: `github.com/Molecule-AI` references migrated to Gitea across docs repo. (`docs` [#3](https://git.moleculesai.app/molecule-ai/docs/pulls/3)) + +--- + +## 2026-05-06 + +### 🧹 Internal + +- **molecule-core org-wide Gitea URL migration**: all `github.com/Molecule-AI` references migrated to `git.moleculesai.app/molecule-ai` across all repos in the org. (`molecule-core`) +- **Hetzner act-runner suspension**: CI runners updated to use `ubuntu-latest` labels following Hetzner act-runner suspension. (`molecule-app` [#1](https://git.moleculesai.app/molecule-ai/molecule-app/pulls/1)) + +--- + +## 2026-04-22 + +### ✨ New features + +#### Workspace model propagation β€” hermes MiniMax flow +Customer selects `model=minimax/MiniMax-M2.7-highspeed` in Canvas β†’ the model and +API key now propagate correctly into the runtime environment instead of being dropped +on the floor at provisioning time. Works for hermes workspaces in both hosted SaaS +and self-hosted EC2 deployments. +(`molecule-core` [#1685](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1685)) + +#### EC2 Instance Connect Endpoint β€” one-click shell from Canvas +Canvas Terminal tab now uses AWS EC2 Instance Connect Endpoint to open a PTY inside +any workspace EC2 instance β€” no SSH keys to manage, no IP to copy, no security group +rules to configure. IAM policy gates access, STS pushes a short-lived key that +auto-expires, and every tunnel open is recorded in CloudTrail. +See the [EC2 Instance Connect guide](/docs/infra/workspace-terminal). +(`molecule-core` [#1554](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1554)) + +#### Phase 33 β€” Cloudflare Tunnel replaced with direct-connect public IPs +Cloud-hosted workspaces no longer route through `cloudflared`. Each workspace gets +its own public IP from the VPC subnet and connects directly to the platform over +TLS on port 443. Reduces latency by ~20–40 ms (region-dependent), removes the +Cloudflare egress cost dependency, and enables direct `curl` debugging without +the tunnel path. +See the [migration blog post](/blog/cloudflare-tunnel-migration). +(`molecule-core` [#1612](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1612)) + +### πŸ”’ Security + +- **F1085 deleteViaEphemeral**: `rm` scope restricted to `/configs` volume only β€” + prevents deletion of application code or workspace files if the exec form is + exploited. Applied to both `main` and `staging`. (`molecule-core` [#1682](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1682), [#1616](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1616)) + +### πŸ”§ Fixes + +- Canvas now fetches the runtime and model dropdown from the `/templates` registry + at load time β€” runtime list stays current without code deploys. (`molecule-core` [#1666](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1666)) +- Canvas accessibility: `aria-hidden` correctly applied to decorative SVGs; + `MissingKeysModal` now uses correct dialog semantics and manages focus. (`molecule-core` [#1594](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1594)) +- Provisioner pulls workspace template images from GHCR instead of Docker Hub + for faster cold starts and reduced third-party dependency. (`molecule-core` [#1624](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1624)) +- Shared runtime heartbeat no longer leaves workspaces in a phantom-busy state after + task completion. (`molecule-ai-workspace-runtime` [#37](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pulls/37)) + +### πŸ“š Docs + +- **MCP server structured logging**: `LOG_LEVEL` env var (`trace`/`debug`/`info`/`warn`/`error`/`fatal`), + pino JSON output in production, pretty-print in development, AsyncLocalStorage + context on every log entry (tool name, request ID, workspace ID). (`docs` [#78](https://git.moleculesai.app/molecule-ai/docs/pulls/78)) +- **molecli shell completion**: tab completion for `molecule` CLI in bash, zsh, fish, + and PowerShell β€” covers all subcommands and flags. (`docs` [#79](https://git.moleculesai.app/molecule-ai/docs/pulls/79)) + +### 🧹 Internal + +- 34 internal changes across `molecule-core`, `molecule-ci`, and template repos: + CI workflow migration to `ubuntu-latest`, security patch backports (CWE-22/CWE-78), + Go build fixes, canvas Dockerfile GID fix, Go linter upgrades, duplicate-symbol + resolution, and reusable `publish-template-image` workflow for all workspace template + repos. (`molecule-core`, `molecule-ci`) + +--- + + + +## 2026-04-17 + +A high-velocity day: 80+ PRs merged across platform, canvas, runtimes, security, and channels. + +### ✨ New features + +#### opencode Integration β€” MCP bridge for AI coding agents +Connect [opencode](https://opencode.ai) to any Molecule AI workspace over a +standard `Authorization: Bearer` remote MCP connection. opencode gains the full +A2A tool surface (`delegate_task`, `list_peers`, `recall_memory`, and more) +via two transports: Streamable HTTP (`POST /workspaces/:id/mcp`) and SSE +(backwards-compat `GET /workspaces/:id/mcp/stream`). Rate-limited to 120 req/min +per token. See the [opencode Integration guide](/docs/opencode). +(#840, #842) + +#### Slack β€” per-agent identity with Bot Token mode +The Slack channel adapter now supports dual-mode outbound: **Bot Token** (new, +recommended) and Incoming Webhook (legacy, unchanged). With a `bot_token` each +workspace posts under its own display name and icon via `chat:write.customize`. +Markdown is automatically converted to Slack `mrkdwn` format. +See [Channels](/docs/channels). +(#844, #851) + +#### AG-UI compatible SSE endpoint +New `GET /workspaces/:id/events` endpoint streams agent events as AG-UI +compatible Server-Sent Events. Enables AG-UI frontend integrations to subscribe +to live workspace activity without polling. +(#601) + +#### A2A topology overlay on the canvas +The canvas now renders a live A2A topology overlay β€” every workspace as a node, +every in-flight delegation as an animated directed edge. Zoom to team, click any +edge to inspect the task payload. +(#751) + +#### Audit trail visualisation panel +A new audit trail panel in the canvas surfaces the HMAC-SHA256 immutable event +log per workspace β€” every task received, LLM call, and completion in +chronological order with chain-of-custody verification. +(#651, #759) + +#### Workspace hibernation β€” auto-pause idle workspaces +Workspaces that receive no tasks for `HIBERNATION_IDLE_MINUTES` (default: 30) +are automatically hibernated (containers paused, resources freed). They +auto-wake on the next inbound task with full state restored. Manage via +`POST /workspaces/:id/hibernate` and `POST /workspaces/:id/wake`. +See [API Reference](/docs/api-reference). +(#724) + +#### Temporal workflow checkpoints β€” step-level persistence +Workspace templates now persist intermediate workflow steps to the database. +On container restart (crash, deploy, hibernate/wake) the workspace resumes from +the last completed step rather than restarting the whole task. Step endpoints +documented in the [API Reference](/docs/api-reference). +(#797, #803) + +#### Semantic memory search +Agent memory is now vector-indexed via pgvector. `recall_memory` accepts an +optional `?q=` parameter for semantic (embedding) search in addition to exact +keyword match. Nearest-neighbour results are ranked by cosine similarity and +colour-coded in the canvas Memory Inspector. +(#784, #787) + +#### Memory Inspector panel +A new canvas panel lets you browse, search, and inspect all `LOCAL` and `TEAM` +memory keys for any workspace β€” live, without leaving the canvas. +(#738) + +#### Hermes β€” stacked system messages +The Hermes runtime now accepts a `system_blocks` list: each block (persona, +tools, reasoning policy) is merged in order rather than overwriting the previous +system prompt. Enables persona stacking for complex multi-role workflows. +See [API Reference](/docs/api-reference) β†’ Runtimes section. +(#655, #798) + +#### Hermes β€” native `tools` parameter +Hermes passes tools to the model via the native `tools=[]` API parameter instead +of text-in-prompt injection. Structured tool definitions, better token efficiency, +and full compatibility with Nous/Hermes-3 tool call format. +(#644) + +#### Hermes β€” structured output (`response_format`) +`response_format=json_schema` is now wired through to the model. Hermes +workspaces can request strict JSON output against a defined schema. +(#645) + +#### AGENTS.md auto-generation +Platform workspaces now auto-generate an `AGENTS.md` file in the workspace +container at boot. The file lists all peer workspaces visible to this workspace, +their roles, and their capabilities β€” giving LLMs automatic context about the +org topology without manual prompt engineering. +(#763) + +#### Discord channel adapter +A new Discord adapter joins Telegram, Slack, and Lark. Configure with a +`bot_token` and `channel_id` to send and receive messages on Discord. +(#656) + +#### Per-workspace budget limits +Set a `budget_limit` (USD) on any workspace. The A2A executor enforces the limit +at task dispatch β€” tasks that would exceed the monthly cap are rejected with a +`429 Budget Exceeded` error. Configure via `PATCH /workspaces/:id`. +(#611, #606) + +#### Per-workspace token metrics +`GET /workspaces/:id/metrics` returns token counts (input, output, cache read/write) +aggregated over rolling 1-hour and 30-day windows. Live usage is displayed in the +canvas WorkspaceUsage panel. +(#602, #627) + +#### Claude Opus 4.7 β€” effort levels and task budget +Workspace config now exposes `effort` (`low` / `medium` / `high` / `xhigh` / +`max`) and `task_budget` (token ceiling) for Anthropic Claude workspaces. +`xhigh` and `max` activate extended thinking (Opus 4.7+ only). Configure in the +Canvas Config tab or via `PATCH /workspaces/:id`. +(#639, #654, #669) + +#### Plugin supply-chain hardening +All plugin refs must now be pinned (no `latest`, no floating branches). Unpinned +refs are blocked at load time unless `PLUGIN_ALLOW_UNPINNED=true`. SHA-256 +integrity checking available for plugin archives. +(#775) + +#### Org-level plugin governance registry +A new per-org allowlist controls which plugins workspaces in that org are +permitted to load. Managed via `POST/DELETE /admin/orgs/:orgId/plugins/allowlist`. +(#610) + +#### Schedule health endpoint +`GET /admin/schedules/health` returns cross-workspace cron health: last-fired, +next-scheduled, consecutive-empty count, and phantom detection status for every +schedule in the org. +(#671, #796) + +#### Fly Machines provisioner +The platform now supports `PROVISIONER=flyio` β€” workspaces are provisioned as +Fly Machines instead of Docker containers or EC2 instances. See the +[self-hosting guide](/docs/self-hosting). +(#578 β€” docs PR #7) + +### πŸ”’ Security + +- **Auth hardening** β€” PATCH `/workspaces/:id` now requires ownership + validation; UUID fields are validated before DB queries; input lengths bounded + across all handlers. (#692, #701) +- **Admin token isolation** β€” `AdminAuth` middleware correctly rejects workspace + bearer tokens when `ADMIN_TOKEN` is set, preventing privilege escalation from + workspace token β†’ admin. (#684, #729) +- **Metrics route auth** β€” `GET /workspaces/:id/metrics` now requires workspace + bearer token; previously it was unauthenticated. (#696) +- **X-Workspace-ID forgery** β€” Requests spoofing the `system-caller/` prefix in + `X-Workspace-ID` headers are rejected. (#766) +- **GLOBAL memory injection safeguards** β€” `commit_memory` with `scope: GLOBAL` + now validates content for prompt injection patterns before persisting. (#769) +- **Security headers** β€” `X-Content-Type-Options: nosniff` and + `X-Frame-Options: DENY` added to all API responses. (#629) +- **Token revocation hardening** β€” Revoked tokens are purged from the in-memory + cache within 60s; previously the cache could serve revoked tokens until TTL + expiry. (#696) +- **MCP server** β€” npm version pinned; `-y` flag removed from install commands. + (SAFE-MCP NEW-003, #808 β€” docs PR #18) +- **Canvas test-token endpoint** β€” gated behind `AdminAuth` and removed from + general router. (#612, #708) + +### πŸ”§ Fixes + +- Fixed `POST /workspaces` not persisting the secrets envelope on create. (#568) +- Fixed self-delegation deadlock when a workspace delegates to itself. (#570) +- Fixed GitHub installation token expiry β€” tokens now refresh automatically before + expiry rather than failing mid-operation. (#567) +- Fixed `TenantGuard` same-origin bypass for EC2 tenant Canvas. (#584) +- Fixed pgvector migration to wrap in `DO` block, eliminating E2E CI failures + from duplicate extension install. (#843, #670, #636) +- Fixed scheduler dropping schedules with `NULL next_run_at` permanently. (#728) +- Fixed `ValidateToken` not checking `removed` workspace status, allowing tokens + for deleted workspaces to authenticate. (#719) +- Fixed canvas hydration error UI, radio keyboard nav, and zoom-to-team + shortcut. (#565) +- Fixed canvas UX: error handling, accessibility, loading state. (#587) +- Fixed canvas deploy preflight to require env keys for Hermes and Gemini CLI + runtimes. (#588) +- Fixed budget/spend counters capping before DB upsert to prevent NUMERIC + overflow. (#630, #634) +- Fixed pgvector TEXTβ†’UUID FK type mismatch in migrations 028 and 031 that + blocked all E2E runs. (#646, #670, #843) +- Fixed duplicate hook firings (3–4Γ—) in `dedup_settings_hooks`. (#551, #597) +- Accessibility fixes: keyboard access on `TeamMemberChip`, `role=alert` on + status banners, close button label, `ProvisioningTimeout` modal. (#841) + +### πŸ“š Docs + +- Google ADK runtime β€” added hands-on Quickstart section. (docs PR #8) +- Hermes β€” full runtime reference page. (docs PR #9) +- AGENTS.md β€” auto-generation documented in concepts. (docs PR #10) +- Semantic memory search β€” `?q=` param documented in API reference. (docs PR #11) +- Canvas A2A topology overlay + audit trail panel. (docs PR #12) +- molecule-medo plugin β€” opt-in platform plugin page. (docs PR #13) +- Workspace hibernation β€” status lifecycle, endpoints, auto-wake behaviour. (docs PR #14) +- molecule-audit-ledger β€” HMAC chain, `/audit` endpoint, `LedgerHooks`, CLI. (docs PR #15) +- Hermes stacked system messages β€” `system_blocks` kwarg. (docs PR #16) +- Plugin supply chain security β€” pinned refs required, SHA-256 integrity. (docs PR #17) +- SAFE-MCP audit report 2026-04-17. (docs PR #18) +- Temporal workflow checkpoints β€” step endpoints, auto-resume behaviour. (docs PR #19) + +--- + +_Changelog entries are compiled by the [Documentation Specialist](https://github.com/Molecule-AI) from all merged pull requests for the day. Times are UTC._