Commit Graph

576 Commits

Author SHA1 Message Date
Molecule AI Research Lead
40671d23a7 chore(eco-watch): update CrewAI entry with Enterprise deep-dive findings (2026-04-17)
Competitive Intelligence completed a full CrewAI Enterprise deep-dive:

- Crew Studio confirmed as a real node-and-edge drag-and-drop canvas (not
  just forms), ships in both SaaS and AMP Factory self-hosted — but paradigm
  is workflow design, not persistent-identity governance. Counter-positioning
  for #582 must be explicit: governance canvas, not just visual canvas.
- AMP Factory self-host is stronger than previously assessed: on-prem or
  private VPC, Kubernetes, full Studio included, FedRAMP High certified.
- A2A support is first-class at v0.8/v0.9 (both client and server modes) —
  Molecule AI orgs can recruit CrewAI agents as workers via standard A2A today.
  Integration opportunity, not just threat.
- Differentiator gaps: CrewAI has 20+ native connectors, agent training,
  checkpoint/fork, FedRAMP High; Molecule AI has persistent identity, org
  hierarchy, governance canvas (#582 pending).

threat_level remains high. FedRAMP gap flagged for enterprise sales tracking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 02:00:40 +00:00
Molecule AI Research Lead
1bcbd614a7 chore(eco-watch): add GitHub MCP Server and Skillshare entries (2026-04-17)
Second eco-watch scan of the day (Go trending + HN :38 run).

**GitHub MCP Server** (github/github-mcp-server, 28.9k, v1.0.0 Apr 16):
GitHub's official MCP Server — 60+ tools (repos, issues, PRs, Actions,
code security). Same "adopt as workspace plugin source" pattern as
Chrome DevTools MCP. Dynamic toolset discovery (beta) is a reference
design for our plugins available endpoint. Added LOW threat.

**Skillshare** (runkids/skillshare, 1.5k, v0.19.2 Apr 14):
Go binary syncing SKILL.md + agent configs across 50+ AI tools via
symlinks. Direct overlap with our plugins/ distribution model and
SKILL.md format. Notable: ships a prompt-injection/exfiltration scanner
on install — we have no equivalent gate in our plugin install path.
Added LOW threat; scanner pattern is an actionable gap.

Both added to YAML snapshot (LOW tier) and Entries narrative.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 02:00:40 +00:00
Molecule AI Research Lead
7ab115fa86 chore(eco-watch): add Cognee and Archestra entries (2026-04-17)
Daily ecosystem survey — two new projects not previously tracked:

**Cognee** (topoteretes/cognee, 15.8k, v1.0.1.dev1 Apr 15):
Hybrid graph+vector knowledge engine for agent memory. Ships a claude-code
plugin for session memory and native Hermes Agent integration. The
four-operation API (remember/recall/forget/improve) and cross-agent
tenant-isolated knowledge graph are directly relevant to closing our
agent_memories gap. Added as LOW threat; watch for a first-class MCP
server release.

**Archestra** (archestra-ai/archestra, 3.6k, platform-v1.2.15 Apr 16):
Enterprise MCP registry + dual-LLM security gateway. Kubernetes-native,
AGPL-3.0. Governs which teams can access which MCP servers, plus a
security sub-agent that intercepts tool responses to block prompt
injection. Complementary to (not competitive with) Molecule AI today;
dual-LLM gateway pattern worth borrowing for A2A proxy hardening.
Added as LOW threat.

Both added to YAML snapshot (LOW tier) and Entries narrative.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 02:00:40 +00:00
molecule-ai[bot]
cc2ab40531 docs(eco-watch): add structured competitor snapshot for PMM cron (#559)
* chore(eco-watch): 2026-04-16 daily survey — OpenAI Sandbox Agents, Tencent AI-Infra-Guard, VoltAgent

Adds three new ecosystem-watch entries:

- OpenAI Agents SDK v0.14 Sandbox Agents (released April 15 2026): SandboxAgent
  with persistent isolated workspaces, snapshot/resume, and sandbox memory across
  7 hosted backends. Directly competes with our workspace lifecycle model.

- Tencent AI-Infra-Guard: MCP server scanning, skills scanning, and agent audit
  platform (3.5k stars, Tencent Zhuque Lab). Enterprise security audits will
  touch our plugin manifests and MCP server surface.

- VoltAgent: TypeScript agent framework + VoltOps Console (8.2k stars, 668 releases).
  Closest Canvas analogue in the TS ecosystem; supervisor/sub-agent coordination
  mirrors our PM delegation chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(eco-watch): add structured competitor snapshot for PMM cron (#537)

Add a machine-readable `## Competitor Snapshot` YAML block to
docs/ecosystem-watch.md so the PMM cron has stable, diff-able fields
(name, slug, date, version, stars, threat_level, notable_changes,
source_url) to parse and detect competitor moves each tick.

Also bootstrap docs/marketing/competitors.md — the PMM cron output
file that was missing, causing every cron run to be a silent no-op.

34 competitors across three threat tiers (HIGH/MEDIUM/LOW). Data
verified by Technical Researcher (version check), Market Analyst
(threat matrix), and Competitive Intelligence (source URLs + notable
changes) as of 2026-04-17.

Key findings incorporated from analyst run:
- Paperclip v2026.416.0 shipped Apr 16 (HIGH — newest escalation)
- Hermes v0.10.0 Tool Gateway launched Apr 16
- Google ADK updated to v1.30.0 (was v1.29.0 in narrative)
- OpenHands actually at v1.6.0 (file showed stale v0.39.0)
- Microsoft Agent Framework upgraded to HIGH (1.0 GA, enterprise dist.)
- Flowise downgraded to LOW (Workday acquisition narrows market)
- Dify corrected to v1.13.3 stable (v1.14.0 was RC-only)

Closes #537

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Molecule AI Research Lead <research-lead@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:38:39 +00:00
molecule-ai[bot]
1225e9429d fix(canvas): hydration error UI (#554), radio arrow-key nav (#556), zoom-to-team context menu (#557) (#565)
- #554 CRITICAL: Add hydrationError state to Zustand store; catch handler now
  calls setHydrationError instead of silent console.error; page renders a
  full-screen zinc-950 error banner with a Retry button that reloads the page
- #556 MEDIUM: Add roving tabIndex + ArrowDown/Up/Left/Right keyboard handler
  to the tier radio group in CreateWorkspaceDialog (WCAG 2.1 compliant)
- #557 MEDIUM: Add "Zoom to Team" menu item to ContextMenu (visible only when
  node has children); dispatches molecule:zoom-to-team for keyboard accessibility
- Bonus: add missing 'use client' directive to RevealToggle.tsx

Co-authored-by: Molecule AI Frontend Engineer <frontend-engineer@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:35:54 +00:00
Hongming Wang
0dd7437fef Merge pull request #550 from Molecule-AI/feat/issue-542-google-adk-adapter
feat(adapters): add google-adk runtime adapter
2026-04-16 17:22:15 -07:00
Hongming Wang
54bacf238e Merge pull request #551 from Molecule-AI/fix/settings-hook-dedup
fix(scripts): dedup_settings_hooks + verify — fix 3-4x duplicate hook firings
2026-04-16 17:22:11 -07:00
c4463dbe8d fix(scripts): add dedup_settings_hooks + verify utilities
molecule_runtime's _deep_merge_hooks() uses unconditional list.extend()
when merging plugin settings-fragment.json files. On every plugin install
or reinstall each hook handler is re-appended, causing 3-4x duplicate
firings per event.

scripts/dedup_settings_hooks.py — idempotent live fix (reads via
/proc/*/root, no docker CLI required). Safe to re-run.
scripts/verify_settings_hooks.py — exits 1 if any container still has
duplicate hooks; used in CI health checks and manual audits.

Upstream fix needed in molecule_runtime._deep_merge_hooks() to
deduplicate by (matcher, frozenset(commands)) before writing. Track
separately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:12:07 +00:00
Molecule AI Backend Engineer
4e14bc71b3 feat(adapters): add Google ADK runtime adapter (#542)
Implements WorkspaceAdapter for Google's Agent Development Kit (google-adk
v1.x, Apache-2.0). Ships four files under workspace-template/adapters/google-adk/:

- adapter.py — GoogleADKAdapter + GoogleADKA2AExecutor (100% test coverage)
- requirements.txt — pinned google-adk==1.30.0 + google-genai>=1.16.0
- README.md — overview, install, usage, config, architecture diagram
- test_adapter.py — 46 unit tests, all passing, no live API calls

Supports AI Studio (GOOGLE_API_KEY) and Vertex AI (GOOGLE_GENAI_USE_VERTEXAI=1).
Model prefix stripping: "google:gemini-2.0-flash" → "gemini-2.0-flash".
Error sanitization mirrors the hermes_executor convention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:08:17 +00:00
Hongming Wang
afc6654dd2 Merge pull request #546 from Molecule-AI/fix/restore-cp-provisioner
fix: restore CP provisioner for EC2 workspace deployment
2026-04-16 14:26:04 -07:00
Hongming Wang
925da9d6c2 fix: restore cp_provisioner.go updated for EC2 backend
The CP provisioner calls POST /cp/workspaces/provision which now
creates EC2 instances (not Fly Machines). The tenant platform
auto-activates this when MOLECULE_ORG_ID is set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:25:43 -07:00
Hongming Wang
19815817c1 Merge pull request #536 from Molecule-AI/feat/issue-496-hermes-reasoning
feat(hermes): HermesA2AExecutor — native reasoning for Hermes 4 via OpenAI-compat API (#496)
2026-04-16 14:15:16 -07:00
Hongming Wang
7871fd7251 Merge pull request #532 from Molecule-AI/fix/issue-450-csp-nonce
fix(canvas): nonce-based CSP replaces unsafe-inline/unsafe-eval in production
2026-04-16 14:15:12 -07:00
Hongming Wang
b4d214692f Merge pull request #543 from Molecule-AI/chore/eco-watch-2026-04-16
chore(docs): eco-watch 2026-04-16 — Paperclip, Google ADK, Chrome DevTools MCP
2026-04-16 14:04:51 -07:00
Hongming Wang
fbe48ba4f0 Merge pull request #538 from Molecule-AI/devrel/gemini-cli-demo
devrel: gemini-cli runtime adapter demo (closes #534)
2026-04-16 14:04:47 -07:00
molecule-ai[bot]
fcee2a1863 docs: brand discoverability audit — Molecule AI SERP pollution (2026-04-16) 2026-04-16 20:46:46 +00:00
Hongming Wang
0bdb0e899e Merge pull request #528 from Molecule-AI/fix/issue-450-csp-api-strict
fix(middleware): strict CSP on API routes, permissive for canvas (#450)
2026-04-16 13:46:20 -07:00
molecule-ai[bot]
def46729e8 Merge pull request #531 from Molecule-AI/docs/devrel-feat-480
docs(devrel): Lark / Feishu channel adapter tutorial (feat #480)
2026-04-16 20:46:19 +00:00
Hongming Wang
a03594db25 Merge pull request #527 from Molecule-AI/feat/issue-493-hermes-provider-picker
feat(canvas): Hermes provider picker + API key field in CreateWorkspaceDialog
2026-04-16 13:46:16 -07:00
Hongming Wang
4cb74b91ed Merge pull request #509 from Molecule-AI/docs/devrel-feat-379
docs(devrel): gemini-cli runtime tutorial (feat #379)
2026-04-16 13:46:13 -07:00
Molecule AI Research Lead
b46f1fe2da docs(ecosystem-watch): add Paperclip, Google ADK, Chrome DevTools MCP entries (2026-04-16)
Three new entries from today's eco-watch scan:

- paperclipai/paperclip (~54.8k ): hierarchical CEO/manager/worker multi-agent
  orchestration with budget constraints and audit trails. Highest-star agent-
  orchestration OSS project tracked; direct conceptual competitor to our "AI company"
  thesis. Signals: watch for persistent memory and visual org chart additions.

- google/adk-python (~19k , v1.29.0): Google's official multi-agent SDK. Pairs with
  Gemini CLI (already tracked) to form Google's full agent stack. Evaluation teams will
  weigh ADK + Gemini CLI vs Molecule AI. Spawns issue #542 (google-adk adapter).

- ChromeDevTools/chrome-devtools-mcp (~35.5k ): official ChromeDevTools MCP server,
  23 tools, already the de facto standard for browser tool use across 29 MCP clients.
  Replaces our bespoke Puppeteer/CDP integration with a standard skill install.
  Spawns issue #540 (browser-automation plugin migration).

GH issues filed: #540 (browser-automation), #541 (budget_limit), #542 (google-adk adapter)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:45:15 +00:00
molecule-ai[bot]
96960fde89 devrel: gemini-cli demo README walkthrough (issue #534) 2026-04-16 20:43:22 +00:00
molecule-ai[bot]
06bf63078f devrel: Makefile for gemini-cli demo (issue #534) 2026-04-16 20:42:35 +00:00
molecule-ai[bot]
99058f60db devrel: gemini-cli demo script (issue #534) 2026-04-16 20:42:33 +00:00
Molecule AI Backend Engineer
b7c8f18ab2 feat(hermes): expose reasoning mode for Hermes 4 via OpenAI-compat API (#496)
Hermes 4 is a hybrid-reasoning model trained on <think> tags; without asking
for thinking we pay flagship $/tok but get non-reasoning quality. This adds a
dedicated HermesA2AExecutor that dispatches to any OpenAI-compat endpoint
(OpenRouter, Nous Portal) and enables native reasoning for Hermes 4 models.

Key decisions:
- ProviderConfig + _reasoning_supported() detect Hermes 4 by model slug
  substring ("hermes-4", "hermes4") — case-insensitive, no config needed
- extra_body={"reasoning": {"enabled": True}} sent only to Hermes 4 entries;
  Hermes 3 path unchanged (no extra_body, no regressions)
- choices[0].message.reasoning + reasoning_details extracted and written to
  an OTEL span (hermes.reasoning) — deliberately NOT echoed in the A2A reply
  so the reasoning trace never contaminates the agent's next-turn context
- API key / base URL default to OPENAI_API_KEY / OPENAI_BASE_URL env vars
  with openrouter.ai/api/v1 as the fallback endpoint
- _client injection parameter for unit tests (no live API calls needed)
- Error sanitization: only exception class name surfaces to user (mirrors
  sanitize_agent_error() convention from cli_executor.py)

Test coverage: 35 tests, 100% coverage on all new code paths including:
  - _reasoning_supported() — Hermes 4/3/unknown/empty/uppercase
  - ProviderConfig — field assignment and capability flags
  - extra_body presence for Hermes 4, absence for Hermes 3
  - reasoning not in A2A reply; _log_reasoning called when trace present
  - reasoning_details forwarded; span attributes set correctly
  - Telemetry failure swallowed (never blocks response)
  - API error → sanitized class-name-only reply
  - cancel() → TaskStatusUpdateEvent(state=canceled)

Full suite: 990 passed, 0 failed (no regressions).

Resolves #496

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:38:45 +00:00
Molecule AI Frontend Engineer
81c26b9fdd fix(canvas): replace unsafe-inline/unsafe-eval with nonce-based CSP (#450)
Removes 'unsafe-inline' and 'unsafe-eval' from script-src in the
production Content-Security-Policy, replacing them with a per-request
nonce + 'strict-dynamic'. This closes the XSS gap reported in #450
where the CSP header gave false assurance.

Key decisions:
- 'strict-dynamic' propagates nonce trust to Next.js dynamic chunk
  imports — no need to enumerate every chunk URL
- style-src retains 'unsafe-inline': React Flow writes inline style=""
  attributes for node positioning which cannot be nonce'd, and CSS
  injection is accepted as significantly lower risk than script injection
- Dev mode keeps the permissive policy so HMR/fast-refresh keep working
- buildCsp() is exported for unit testing (21 tests added)

Additional hardening in production CSP:
  object-src 'none', base-uri 'self', frame-ancestors 'none',
  upgrade-insecure-requests, connect-src limited to wss: (not ws:)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:35:27 +00:00
molecule-ai[bot]
1e3cf704ec docs: add Gemini CLI landing page brief for /runtimes/gemini-cli (issue #514) 2026-04-16 20:34:32 +00:00
molecule-ai[bot]
26916cc86d docs: add Gemini CLI keyword research (issue #514) 2026-04-16 20:33:32 +00:00
molecule-ai[bot]
04eb546341 docs(devrel): Lark/Feishu channel tutorial for PR #480 2026-04-16 20:32:48 +00:00
Hongming Wang
f3c229db83 Merge pull request #508 from Molecule-AI/fix/507-crlf-hook-breakage
fix: enforce LF for .py hook files — fix #507 (all agents "no response generated")
2026-04-16 13:30:48 -07:00
Molecule AI Backend Engineer
f88f221dfe fix(middleware): split CSP by route type — strict for API, permissive for canvas (#450)
API routes return JSON and never need 'unsafe-inline' or 'unsafe-eval'.
Serving those directives globally defeated the purpose of CSP and gave
false security assurance. Canvas-proxied routes (NoRoute → Next.js) keep
'unsafe-inline' because React hydration requires it; 'unsafe-eval' was
already absent and is confirmed unnecessary in production builds.

Implementation:
- Add isAPIPath() helper with an explicit prefix allowlist that mirrors
  the routes registered in router/router.go
- Strict "default-src 'self'" on all /workspaces, /registry, /health,
  /admin, /metrics, /settings, /bundles, /org, /templates, /plugins,
  /webhooks, /channels, /ws, /events, /approvals paths
- Permissive CSP (unsafe-inline, no unsafe-eval) on canvas/NoRoute paths
- 4 new test functions: TestCSPAPIRoutesGetStrictPolicy (covers every
  prefix + sub-path), TestCSPCanvasRoutesGetPermissivePolicy, and
  TestIsAPIPath unit test including substring-non-match guard

Resolves #450

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:26:17 +00:00
Molecule AI Frontend Engineer
f936af3181 feat(canvas): hermes provider picker in CreateWorkspaceDialog (#493)
When the user sets template="hermes", surface a provider dropdown
(15 providers, defaulting to anthropic) and a masked API key input.
On submit the chosen key is sent as `secrets: { [ENV_VAR]: key }` so
the backend can persist it encrypted before the container boots,
fixing the silent preflight failure reported in #493.

- Adds HERMES_PROVIDERS constant (exported for tests)
- Validates API key presence before POST when template is hermes
- Uses violet accent to visually distinguish the hermes section
- 11 new unit tests covering picker visibility, default, env-var
  mapping, validation, and POST payload shape

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:25:58 +00:00
molecule-ai[bot]
0320b71315 docs(devrel): gemini-cli runtime tutorial for PR #379 2026-04-16 20:22:26 +00:00
rabbitblood
995f51f950 fix: enforce LF for .py hook files to fix #507
CRLF line endings in .claude hook files caused claude-code SessionStart
hooks to fail silently on Windows checkouts — python3 received a filename
ending in '\r' (e.g. 'session-start-context.py\r'), failed with ENOENT,
and the claude-code query short-circuited with result='' across every
A2A call. Observed symptom: all 22 agents returned '(no response
generated)' on every pulse despite the model never being called
(input_tokens=0, output_tokens=0).

Existing *.sh rule covered the shebang line; adding *.py covers the
Python hook target that the shell script invokes. Shipped alongside
the same fix in molecule-ai-plugin-molecule-session-context (which
is the primary source of these hooks via the platform plugin loader).

Fixes #507

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:18:17 -07:00
Hongming Wang
e76aee6022 Merge pull request #506 from Molecule-AI/feat/github-app-auth-plugin
feat(platform): wire github-app-auth plugin for per-installation tokens
2026-04-16 12:59:11 -07:00
rabbitblood
2492f8c806 feat(platform): wire github-app-auth plugin for per-installation tokens
Integrates github.com/Molecule-AI/molecule-ai-plugin-github-app-auth.
When GITHUB_APP_ID is set, the platform constructs a plugin
Authenticator at boot and registers it as an EnvMutator on the
WorkspaceHandler. Every workspace provision then gets a fresh
GITHUB_TOKEN / GH_TOKEN injected from the App's installation token
(rotates ~hourly, refresh 5 min before expiry).

Verified live this turn:
- Platform boot log: `github-app-auth: registered, 1 mutator(s) in chain`
- `docker exec ws-<id> gh auth status` → `Logged in as molecule-ai[bot] (GH_TOKEN)`
- `gh issue list --repo Molecule-AI/molecule-core` returns real data
  (Hermes #498/#499/#500 visible from inside a workspace container)

## Changes
- platform/go.mod + go.sum: new dep on the plugin
- platform/cmd/server/main.go: import + conditional registration
  (soft-skip when GITHUB_APP_ID is unset for self-hosted/dev)
- docker-compose.yml: pass GITHUB_APP_* env + bind-mount private key

## Drive-by
.gitignore: exclude /org-templates /plugins /workspace-configs-templates
— these dirs are populated locally by clone-manifest.sh from the
standalone repos, should never be committed to core. Without this rule
my previous git add -A staged 33 embedded git dirs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:52:20 -07:00
Hongming Wang
7bfb91d46a Merge pull request #504 from Molecule-AI/fix/code-review-final-batch
fix: code review — dead code, DRY, rate limit, docs
2026-04-16 12:09:53 -07:00
Hongming Wang
8f4d0997c8 fix: code review findings — dead code, DRY, rate limit, docs
1. Delete fly_provisioner.go — superseded by control plane architecture.
   Direct Fly provisioning from tenant was intentionally removed.

2. Extract loadWorkspaceSecrets() — shared by Docker + CP provisioner
   paths. Eliminates 30-line secret-loading duplication.

3. Token rate limit — max 50 active tokens per workspace. Returns 429
   if exceeded. Prevents unbounded token creation by compromised client.

4. CLAUDE.md — add GET/POST/DELETE /workspaces/:id/tokens to route table.

5. .env.example — document MOLECULE_ORG_ID and CP_PROVISION_URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:04:37 -07:00
Hongming Wang
77d42268d4 Merge pull request #503 from Molecule-AI/feat/controlplane-provisioner
feat(platform): control plane provisioner (CONTAINER_BACKEND=controlplane)
2026-04-16 11:54:07 -07:00
Hongming Wang
a152342e8c feat(platform): auto-detect SaaS tenant → control plane provisioner
No env vars to configure. The platform auto-detects the backend:

  MOLECULE_ORG_ID set → SaaS tenant → control plane provisioner
  MOLECULE_ORG_ID empty → self-hosted → Docker provisioner

The control plane URL defaults to https://api.moleculesai.app (override
with CP_PROVISION_URL for testing). No FLY_API_TOKEN on the tenant.

Removed: direct Fly provisioner (FlyProvisioner) — all SaaS workspace
provisioning goes through the control plane which holds the Fly token
and manages billing, quotas, and cleanup.

Two backends: CPProvisioner (SaaS) and Docker Provisioner (self-hosted).

Closes #494

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:50:52 -07:00
Hongming Wang
2cecd4ee3d Merge pull request #502 from Molecule-AI/fix/update-delete-same-origin
fix(auth): nesting + delete from tenant canvas
2026-04-16 11:26:27 -07:00
Hongming Wang
3db589770e fix(auth): allow nesting + delete from tenant canvas (same-origin)
PATCH /workspaces/:id field-level auth for parent_id/tier/runtime
required a bearer token, blocking canvas nesting (drag-to-nest).
Added IsSameOriginCanvas check so the tenant canvas can update
sensitive fields without a bearer.

Exported IsSameOriginCanvas from middleware package so workspace.go
can call it for the field-level auth path.

DELETE /workspaces/:id is behind AdminAuth which already has the
same-origin check — if delete still fails, it's a different issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:22:45 -07:00
Hongming Wang
bb25d54daa Merge pull request #501 from Molecule-AI/feat/fly-provisioner
feat(platform): Fly Machines provisioner (CONTAINER_BACKEND=flyio)
2026-04-16 11:05:52 -07:00
Hongming Wang
c2c80fd269 feat(platform): Fly Machines provisioner for SaaS workspace deployment
When CONTAINER_BACKEND=flyio, workspaces are provisioned as Fly Machines
instead of local Docker containers. This enables workspace deployment
on SaaS tenants where no Docker daemon is available.

New files:
- provisioner/fly_provisioner.go: FlyProvisioner with Start/Stop/
  IsRunning/Restart/Close via Fly Machines API (api.machines.dev/v1)
- FlyRuntimeImages maps runtimes to GHCR image tags

Changes:
- main.go: select Docker vs Fly based on CONTAINER_BACKEND env var
- workspace.go: SetFlyProvisioner() setter, Create checks flyProv first
- workspace_provision.go: provisionWorkspaceFly() loads secrets, calls
  FlyProvisioner.Start, issues auth token for the new machine

Env vars for Fly backend:
- CONTAINER_BACKEND=flyio (activates Fly provisioner)
- FLY_API_TOKEN (Fly deploy token)
- FLY_WORKSPACE_APP (Fly app name for workspace machines)
- FLY_REGION (default: ord)

Closes #494

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 10:51:15 -07:00
Hongming Wang
bb44b1f03b Merge pull request #491 from Molecule-AI/fix/code-review-findings-batch
fix: token UI, auth hardening, WS dedup, pagination
2026-04-16 10:46:28 -07:00
Hongming Wang
54bb543ff7 fix: code review findings — token UI, auth hardening, WS dedup
1. Settings panel: wire TokensTab into "API Tokens" tab (was imported
   but not rendered). Rename "API Keys" → "Secrets", add "API Tokens"
   tab. Fix docs link → doc.moleculesai.app/docs/tokens.

2. Referer match hardening: require exact host match or trailing slash
   to prevent evil.com subdomain bypass. Cache CANVAS_PROXY_URL at
   init time instead of per-request os.Getenv.

3. Extract shared deriveWsBaseUrl() to lib/ws-url.ts — eliminates
   duplicate 12-line derivation in socket.ts and TerminalTab.tsx.

4. Token list pagination: add ?limit= and ?offset= params (default
   50, max 200) to GET /workspaces/:id/tokens.

507/507 canvas tests pass, Go build + vet clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 10:42:26 -07:00
Hongming Wang
5d4ee18c72 Merge pull request #490 from Molecule-AI/fix/workspace-auth-same-origin
fix(auth): WorkspaceAuth same-origin canvas on tenant
2026-04-16 10:17:12 -07:00
Hongming Wang
807b4c1b45 fix(auth): allow same-origin canvas requests through WorkspaceAuth on tenant
WorkspaceAuth only accepted bearer tokens, blocking the canvas from
calling per-workspace routes (restart, config, secrets, chat) on the
tenant image where canvas + API share the same origin.

Added isSameOriginCanvas() fallback (same check used by AdminAuth):
checks Referer matches request Host, gated behind CANVAS_PROXY_URL
so only tenant deployments are affected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 10:06:33 -07:00
Hongming Wang
6ea559079e Merge pull request #489 from Molecule-AI/fix/tenant-dockerfile-in-publish
fix(ci): use Dockerfile.tenant for Fly registry (Go + Canvas)
2026-04-16 09:34:44 -07:00
Hongming Wang
c5ef9a71fc fix(ci): use Dockerfile.tenant for Fly registry image (Go + Canvas)
The publish workflow was pushing platform/Dockerfile (Go-only) to the
Fly registry, but tenant machines run the combined image (Go + Canvas
reverse proxy). This caused "canvas unavailable" after machine update.

Changes:
- Fly registry build: platform/Dockerfile → platform/Dockerfile.tenant
- GHCR: keeps Go-only image (for self-hosted/dev use)
- Path triggers: add canvas/** and manifest.json (tenant image includes both)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:31:51 -07:00