Commit Graph

622 Commits

Author SHA1 Message Date
Molecule AI Backend Engineer
f99d8b0a1a feat(platform): add per-workspace budget_limit field and A2A enforcement (#541)
- Migration 025: ADD COLUMN budget_limit BIGINT DEFAULT NULL and
  monthly_spend BIGINT NOT NULL DEFAULT 0 to workspaces table
- Models: BudgetLimit *int64 in CreateWorkspacePayload;
  MonthlySpend int64 in HeartbeatPayload
- workspace.go: scanWorkspaceRow, workspaceListQuery, Get, Create, and
  Update all handle budget_limit/monthly_spend; budget_limit is gated
  as a sensitiveUpdateField
- registry.go: heartbeat conditionally writes monthly_spend only when
  payload.MonthlySpend > 0 (avoids overwriting with zero)
- a2a_proxy.go: checkWorkspaceBudget() returns 429 when
  monthly_spend >= budget_limit (NULL = no limit; fail-open on DB error)
- Tests: 8 new workspace_budget_test.go tests + patched existing tests
  for the 20-column scanWorkspaceRow and 10-param CREATE INSERT

Field type: BIGINT (int64), units: USD cents (budget_limit=500 = $5.00/month)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:18:41 +00:00
Molecule AI Backend Engineer
f5c9132413 fix(migrations): close 024→026 gap — rename 026→025 token_usage, 027→026 allowlist (#631)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:17:36 +00:00
molecule-ai[bot]
19396fc55a Merge pull request #628 from Molecule-AI/fix/issue-623-adminauth-origin-bypass
Merge gate passed (all 7 gates). Security fix: removes canvasOriginAllowed + isSameOriginCanvas Origin bypass from AdminAuth — bearer token is now the only accepted credential on admin routes. 3 regression tests cover forged-localhost, forged-tenant-domain, and bearer+Origin golden path. Auth PR — CEO explicit approval confirmed in chat. UNSTABLE = known GitHub App token scope gap.
2026-04-17 06:13:33 +00:00
molecule-ai[bot]
67ee0366e0 Merge pull request #606 from Molecule-AI/feat/issue-541-budget-limit-frontend
Merge gate passed (all 7 gates). All merge conflicts were mechanically additive (BudgetSection + WorkspaceUsage both kept; hydrating spinner + error banner combined; useId import preserved; WCAG a11y tests kept). UNSTABLE = known GitHub App token scope gap, not a test failure.
2026-04-17 06:10:53 +00:00
Molecule AI Frontend Engineer
6668a95d6f fix(canvas): use explicit empty-string check in BudgetSection to preserve zero-credit budget
parseInt("0", 10) || null evaluates to null, silently converting a
zero-credit budget to unlimited. Switch to raw !== "" ? parseInt() : null
so budget_limit: 0 is sent correctly. Adds regression test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:07:08 +00:00
Molecule AI Frontend Engineer
e22d2d2257 fix(canvas): WCAG SC 1.3.1 — programmatic label/input association in InputField
Adds useId() to the InputField helper in CreateWorkspaceDialog so every
<label> is wired to its <input> via htmlFor/id. Without this, screen readers
announced only the placeholder text, not the field name (WCAG 2.1 SC 1.3.1
Level A violation, build 4JIwTGVMjDGNLO8iMGJeC).

Affected fields: Name (required), Role, Budget limit (USD), Template.
The Hermes provider fields were already correctly wired.

Adds 6 new tests in CreateWorkspaceDialog.a11y.test.tsx verifying htmlFor/id
round-trips for each field and unique-id non-collision (602 total, all pass;
build clean; 'use client' grep empty).

Note: #554 (hydration error UI) and #556 (tier radio arrow-key nav) are
confirmed fixed in commit e70bb94 — audit cycle 2 was run against the
pre-fix build. #557 (zoom-to-team Z key) is a false positive — the handler
IS implemented; closing via Dev Lead once token is refreshed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:07:08 +00:00
Molecule AI Frontend Engineer
b522484e2e feat(#541): budget settings UI with usage stats and 402 handling
Adds a dedicated BudgetSection component to the workspace details panel:
- GET /workspaces/:id/budget on mount — populates live stats (used/limit/remaining)
- Stats row + blue-500 progress bar (capped at 100%; hidden when unlimited)
- PATCH /workspaces/:id/budget for saving; input blank → budget_limit: null
- "Budget exceeded — messages blocked" amber/zinc-950 banner on any 402 response
  (GET or PATCH); banner clears on a successful subsequent save
- 'use client'; dark zinc theme throughout (zinc-800/700 inputs, blue-500 accents)

DetailsTab refactored: inline budget_limit fields removed; BudgetSection mounted
as a self-contained section between Workspace and Skills. PATCH /workspaces/:id
body no longer includes budget_limit — that concern is isolated to BudgetSection.

Tests: 21 new cases in BudgetSection.test.tsx (loading, stats, progress bar,
save, 402 GET, 402 PATCH, banner clear, non-402 errors). BudgetLimit.DetailsTab
rewritten to mock BudgetSection and verify the DetailsTab/BudgetSection
integration contract (596 total, all pass; build clean; 'use client' grep empty).

API shape: GET/PATCH /workspaces/:id/budget → {budget_limit: int64|null,
budget_used: int64, budget_remaining: int64|null}

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:07:07 +00:00
Molecule AI Frontend Engineer
07240e7095 feat(canvas): budget_limit input in workspace creation and settings UI (#541)
- Adds optional Budget limit (USD) numeric field to CreateWorkspaceDialog;
  blank = null (unlimited), populated = parsed float sent as budget_limit in
  POST /workspaces body
- Adds budget_limit field to DetailsTab edit form; saves via
  PATCH /workspaces/:id; pre-fills from current WorkspaceNodeData
- Shows 'Budget limit exceeded' warning badge when budgetUsed > budgetLimit
  (forward-compatible — badge hidden when budgetUsed is absent)
- Extends WorkspaceData, WorkspaceNodeData, and buildNodesAndEdges to carry
  budgetLimit / budgetUsed fields ready for backend hydration (issue #541 BE PR)
- Ships 22 new tests across CreateWorkspaceDialog and BudgetLimit.DetailsTab
  suites (575 total, all passing); npm run build clean; 'use client' grep empty

API shape confirmed from workspace.go and CreateWorkspacePayload struct:
  field name: budget_limit | type: number | null | units: USD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:06:36 +00:00
Molecule AI Backend Engineer
4810863a40 fix(security): remove canvasOriginAllowed from AdminAuth middleware (#623)
The Origin header is trivially forgeable by any container on the Docker
network. Having canvasOriginAllowed() / isSameOriginCanvas() as auth
bypass paths in AdminAuth let any curl/container without a bearer token
reach /settings/secrets, /bundles/import, /bundles/export, /events, and
all other AdminAuth-gated routes by forging Origin: http://localhost:3000.

Fix: remove both Origin bypass branches from AdminAuth. Bearer token is
now the only accepted credential. Lazy-bootstrap fail-open (zero tokens →
pass-through) is preserved for fresh installs.

CanvasOrBearer retains the Origin bypass because it is scoped exclusively
to cosmetic routes (PUT /canvas/viewport) where a forged request has zero
security impact — worst case is viewport position corruption.

Added 3 regression tests:
- TestAdminAuth_623_ForgedOrigin_Returns401
- TestAdminAuth_623_ForgedCORSOrigin_Returns401
- TestAdminAuth_623_ValidBearer_WithOrigin_Passes

Closes #623, Closes #626

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:00:45 +00:00
molecule-ai[bot]
652019afcc Merge pull request #610 from Molecule-AI/feat/issue-591-org-plugin-allowlist
feat(platform): per-org plugin governance registry (allowlist)
2026-04-17 05:55:27 +00:00
molecule-ai[bot]
b3963da815 Merge pull request #602 from Molecule-AI/feat/issue-593-workspace-token-tracking
feat(platform): per-workspace token tracking + GET /workspaces/:id/metrics
2026-04-17 05:54:27 +00:00
molecule-ai[bot]
09c761dcdb Merge pull request #612 from Molecule-AI/fix/test-token-adminauth
fix(security): gate test-token endpoint behind AdminAuth
2026-04-17 05:53:49 +00:00
molecule-ai[bot]
3bb3737d5c Merge pull request #601 from Molecule-AI/feat/issue-590-agui-sse-endpoint
feat(platform): AG-UI compatible SSE endpoint for streaming agent events
2026-04-17 05:45:29 +00:00
Molecule AI Backend Engineer
9733317609 feat(platform): per-org plugin governance registry (#591)
Add an org-scoped allowlist table so org admins can restrict which plugins
workspace agents are allowed to install.  An empty allowlist means
allow-all (backward-compatible with existing deployments).

• migrations/027_org_plugin_allowlist.{up,down}.sql — new table + unique
  index on (org_id, plugin_name)
• handlers/org_plugin_allowlist.go — resolveOrgID, checkOrgPluginAllowlist
  (fail-open on DB errors), GetAllowlist, PutAllowlist (atomic tx replace)
• handlers/org_plugin_allowlist_test.go — 23 unit tests covering all
  handler paths, resolveOrgID, and all checkOrgPluginAllowlist branches
• handlers/plugins_install.go — allowlist gate between resolveAndStage and
  deliverToContainer; returns 403 if plugin is blocked
• router/router.go — GET/PUT /orgs/:id/plugins/allowlist under AdminAuth

All tests pass; go build ./... clean; gosec Issues: 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 05:40:23 +00:00
molecule-ai[bot]
6c72958e80 Merge pull request #600 from Molecule-AI/feat/issue-592-workspace-cost-transparency
feat(canvas): scaffold WorkspaceUsage component for #592
2026-04-17 05:32:40 +00:00
Molecule AI Backend Engineer
57f5659f74 feat(platform): per-workspace token tracking + GET /workspaces/:id/metrics (#593)
Migration 026 adds workspace_token_usage table (uuid pk, workspace_id FK with
CASCADE, period_start TIMESTAMPTZ, input_tokens, output_tokens, call_count,
estimated_cost_usd NUMERIC(12,6), updated_at) with a UNIQUE index on
(workspace_id, period_start) for day-granularity upserts.

A2A proxy (proxyA2ARequest) now spawns a detached goroutine after each
successful call to extractAndUpsertTokenUsage, which:
  1. Parses usage.input_tokens / usage.output_tokens from result.usage
     (JSON-RPC wrapper) with fallback to top-level usage (direct Anthropic).
  2. Calls upsertTokenUsage — INSERT ... ON CONFLICT DO UPDATE so multi-
     call days accumulate correctly. Estimated cost = input×$0.000003 +
     output×$0.000015 (Claude Sonnet default; adjustable in a later phase).
  Token tracking never blocks the critical A2A path.

New endpoint: GET /workspaces/:id/metrics (wsAuth — WorkspaceAuth bearer
bound to :id). Returns:
  {"input_tokens":N,"output_tokens":N,"total_calls":N,
   "estimated_cost_usd":"0.000000","period_start":"...","period_end":"..."}
404 if workspace missing. Period is current UTC day.

11 new tests (4 handler + 7 parse-unit); 19/19 packages pass.

Closes #593

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 05:29:10 +00:00
molecule-ai[bot]
1473b72e34 Merge pull request #597 from Molecule-AI/fix/issue-566-deep-merge-hooks-dedup
fix(plugins_registry): deduplicate handlers in _deep_merge_hooks() — closes #566
2026-04-17 05:28:49 +00:00
2c80f5fe82 fix(plugins_registry): deduplicate handlers in _deep_merge_hooks()
Unconditional list.extend() on repeated plugin install caused every
hook handler to be appended on each reinstall, leading to 3-4x duplicate
firings per event (PreToolUse, PostToolUse, Stop, etc.).

Fix: before appending each incoming handler, compute a fingerprint of
(matcher, frozenset-of-commands). Skip append if the fingerprint is
already present in the merged list. First-time installs are unaffected —
new handlers still land correctly.

Adds 7 unit tests covering: first install, double install, triple install,
different-matcher co-existence, different-command co-existence, existing
user hook preservation, and top-level key merge semantics.

Closes #566

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 05:22:00 +00:00
Molecule AI Frontend Engineer
1e0c2eed3b feat(canvas): scaffold WorkspaceUsage component for #592
Adds WorkspaceUsage component to canvas/src/components/ with three
placeholder stat rows (Input tokens, Output tokens, Estimated cost)
and a "pending #593" badge. Wires into DetailsTab between the Workspace
and Skills sections. No API calls yet — fetch logic will be added once
GET /workspaces/:id/metrics lands in #593.

9 tests in WorkspaceUsage.test.tsx; all 548 canvas tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 05:16:57 +00:00
Molecule AI Backend Engineer
518a09a911 feat(platform): AG-UI compatible SSE endpoint for streaming agent events (#590)
- Add in-process SSE subscription mechanism to Broadcaster (SubscribeSSE,
  deliverToSSE) so both RecordAndBroadcast *and* BroadcastOnly fan out to
  SSE subscribers — critical because BroadcastOnly skips Redis pub/sub and
  would be invisible to a Redis-only subscriber (AGENT_MESSAGE, A2A_RESPONSE,
  TASK_UPDATED are all BroadcastOnly events).
- Add handlers/sse.go: SSEHandler.StreamEvents sets text/event-stream headers,
  checks workspace existence (404 if missing), subscribes via broadcaster, and
  wraps each WSMessage in an AG-UI envelope:
    data: {"type":"<event>","timestamp":<unix_ms>,"data":{...}}\n\n
- Register wsAuth.GET("/workspaces/:id/events/stream") behind existing
  WorkspaceAuth middleware — bearer token bound to :id.
- Add 6 tests: Content-Type, initial ping, AG-UI format, workspace filter
  (cross-workspace events not leaked), 404 on missing workspace, multiple
  sequential events.

All 19 packages pass. Build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 05:16:51 +00:00
Hongming Wang
50a59655ff Merge pull request #589 from Molecule-AI/docs/ecosystem-maf-v1
docs(ecosystem): update MAF with v1.0 GA + AG-UI competitive findings
2026-04-16 22:06:42 -07:00
Hongming Wang
303e383083 Merge pull request #588 from Molecule-AI/fix/hermes-preflight-keys
fix(canvas): add hermes + gemini-cli to deploy preflight required keys
2026-04-16 22:06:28 -07:00
Hongming Wang
62bd20b01b docs(ecosystem): update MAF entry with v1.0 GA + AG-UI findings
MAF v1.0 shipped April 7 with multi-agent orchestration, native A2A+MCP,
AG-UI SSE protocol for streaming events to frontends. AG-UI is a direct
competitor to our WebSocket canvas. Added actionable gaps: AG-UI endpoint,
tool governance registry, cost transparency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 21:53:49 -07:00
Hongming Wang
6cecf44f45 fix(canvas): add hermes + gemini-cli to deploy preflight required keys
Hermes requires OPENROUTER_API_KEY (or any of its 15 providers).
Gemini CLI requires GOOGLE_API_KEY. Without these entries, the
MissingKeysModal doesn't fire and workspaces start without keys,
causing crash loops.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 21:45:54 -07:00
Hongming Wang
b588b7f23b Merge pull request #587 from Molecule-AI/fix/canvas-ux-polish
fix(canvas): 5 UX polish fixes — error handling, a11y, loading state
2026-04-16 21:44:29 -07:00
Hongming Wang
d4696a5977 fix(canvas): 5 UX polish fixes — error handling, a11y, loading state
1. ScheduleTab + ChannelsTab: wrap toggle/delete in try/catch with
   error feedback (was silently swallowing API failures)
2. MemoryTab: "+Add" button now auto-expands Advanced section
3. SidePanel: keyboard-navigated tabs scroll into view
4. TracesTab: emoji aria-hidden, env-var hint in <details>
5. page.tsx: show Spinner while hydrating instead of flash of EmptyState

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 21:39:44 -07:00
Hongming Wang
420bef2e02 Merge pull request #586 from Molecule-AI/fix/remove-brand-monitor
chore: remove brand-monitor from monorepo
2026-04-16 21:01:12 -07:00
Hongming Wang
7a7f8442d7 chore: remove brand-monitor from monorepo
Standalone operational tool — doesn't belong in the platform core.
Should live in its own repo if needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 21:00:58 -07:00
Molecule AI Backend Engineer
c84171df72 fix(security): add AdminAuth to /admin/workspaces/:id/test-token route
Without middleware, any caller on a non-production instance could mint a
bearer token for any workspace UUID with no authentication. AdminAuth is
defence-in-depth: on a fresh install (no tokens yet) it is fail-open so
the bootstrap path still works; once the first workspace enrolls a token
all callers must present a valid bearer.

Adds two router-level tests confirming the gate:
- TestTestTokenRoute_RequiresAdminAuth_WhenTokensExist → 401 with no header
- TestTestTokenRoute_FailOpenOnFreshInstall → 200 (bootstrap path intact)

Env-var gating inside GetTestToken is retained as a second layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 02:48:00 +00:00
Hongming Wang
6b4c2d3877 Merge pull request #564 from Molecule-AI/feat/issue-549-x-brand-monitor
feat(brand-monitor): X API pay-per-use brand monitor with surge mode → Slack
2026-04-16 19:15:12 -07:00
Hongming Wang
dbe7bcd3a4 Merge pull request #577 from Molecule-AI/docs/blog-deploy-anywhere-561
docs(blog): deploy anywhere — Fly Machines + control plane provisioners
2026-04-16 18:47:38 -07:00
Hongming Wang
54e1129692 Merge pull request #578 from Molecule-AI/docs/devrel-feat-525
docs(devrel): Fly Machines provisioner tutorial (feat #501, closes #525)
2026-04-16 18:47:17 -07:00
Hongming Wang
e7307a76c0 Merge pull request #555 from Molecule-AI/docs/devrel-feat-hermes-multimodel
docs(devrel): Hermes multi-provider dispatch tutorial (Phase 2a/2b/2c)
2026-04-16 18:47:14 -07:00
Hongming Wang
8b03dbb01e Merge pull request #585 from Molecule-AI/fix/publish-remove-fly
fix(ci): remove Fly registry from publish, push tenant to GHCR
2026-04-16 18:26:46 -07:00
Hongming Wang
440e09b360 fix(ci): remove Fly registry from publish pipeline, push tenant to GHCR
Fly.io was deleted — EC2 tenant instances now pull from GHCR.
- Remove Fly registry push step (401 Unauthorized since Fly deleted)
- Remove flyctl deploy step
- Push tenant image to ghcr.io/molecule-ai/platform-tenant instead
- Simplify GHCR auth config (remove Fly token)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 18:26:26 -07:00
Hongming Wang
286a845239 Merge pull request #584 from Molecule-AI/fix/tenant-guard-same-origin
fix(auth): TenantGuard same-origin bypass for EC2 tenant Canvas
2026-04-16 18:25:16 -07:00
Hongming Wang
b73da288e3 fix(auth): TenantGuard same-origin bypass for EC2 tenant Canvas
On EC2 tenant instances, Caddy serves Canvas (:3000) and API (:8080) under
the same domain. Canvas makes same-origin requests without X-Molecule-Org-Id
or Fly-Replay-Src headers, causing TenantGuard to 404 every API route.

- Add isSameOriginCanvas() as tertiary check in TenantGuard — when
  CANVAS_PROXY_URL is set and Referer/Origin matches Host, pass through.
- Enhance isSameOriginCanvas() to also check Origin header (WebSocket
  upgrade requests send Origin but may not send Referer).
- Add 3 new tests: Referer bypass, Origin bypass (WS), inactive without env.

Fixes all 404s on /workspaces, /templates, /org/templates, /approvals/pending,
/canvas/viewport, and /ws WebSocket on tenant EC2 instances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 18:22:23 -07:00
Hongming Wang
59f5c1a3c7 Merge pull request #569 from Molecule-AI/docs/devrel-feat-550
docs(devrel): Google ADK runtime tutorial (feat #550)
2026-04-16 18:17:33 -07:00
molecule-ai[bot]
3b5affb0d1 fix(github): refresh installation token when TTL < 10 min (#547) (#567)
Root cause: the github-app-auth plugin injects GH_TOKEN + GITHUB_TOKEN
into each workspace container's env at provision time (EnvMutator). Those
are GitHub App installation tokens with a fixed ~60 min TTL. The plugin
has an in-process cache that proactively refreshes 5 min before expiry —
but the workspace env is set once at container start and never updated.
Any workspace alive >60 min ends up with an expired token.

Fix (Option B — on-demand endpoint):

pkg/provisionhook:
  - Add TokenProvider interface: Token(ctx) (token, expiresAt, error)
    Lives in pkg/ (public) so the github-app-auth plugin can implement it.
  - Add Registry.FirstTokenProvider() — discovers the first mutator that
    also satisfies TokenProvider via interface assertion. Safe under
    concurrent reads (existing RWMutex).

platform/internal/handlers/github_token.go:
  - New GitHubTokenHandler serving GET /admin/github-installation-token
  - Delegates to the registered TokenProvider (plugin cache — always fresh)
  - 404 if no GitHub App configured, 500 + [github] prefix log on error
  - Never logs the token itself

platform/internal/handlers/workspace.go:
  - Add TokenRegistry() getter so the router can wire the handler without
    coupling to WorkspaceHandler internals

platform/internal/router/router.go:
  - Register GET /admin/github-installation-token under AdminAuth

workspace-template/:
  - scripts/molecule-git-token-helper.sh — git credential helper; calls
    the platform endpoint on every push/fetch; falls through to next
    helper (operator PAT) if platform unreachable
  - entrypoint.sh — configure the credential helper at startup

Why Option B over Option A (background goroutine):
  - The plugin already has its own cache refresh; nothing to refresh here.
  - Pushing env updates into running containers requires docker exec, which
    the architecture explicitly rejects (issue #547 "Alternatives").
  - Pull-based is stateless, trivially testable, zero extra goroutines.

Closes #547

Co-authored-by: Molecule AI DevOps Engineer <devops-engineer@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:47:03 +00:00
molecule-ai[bot]
21f9e70b75 fix(platform): reject self-delegation to prevent _run_lock deadlock (#570)
When a workspace delegated a task to itself, it would acquire
_run_lock twice on the same goroutine mutex, blocking permanently.

Add an early-return guard in `DelegationHandler.Delegate` that
returns HTTP 400 {"error": "self-delegation not permitted"} as soon
as sourceID == body.TargetID, before any DB or A2A work is done.

Adds TestDelegate_SelfDelegation_Rejected to delegation_test.go.

Closes #548

Co-authored-by: Molecule AI Backend Engineer <backend-engineer@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:46:20 +00:00
molecule-ai[bot]
a73de2451c fix(platform): persist secrets envelope from POST /workspaces payload (#568)
`CreateWorkspacePayload` was missing a `Secrets` field, so any
`secrets: { KEY: value }` included in a POST /workspaces body was
silently dropped by ShouldBindJSON.

Changes:
- Add `Secrets map[string]string` field to `CreateWorkspacePayload`
- Wrap workspace INSERT in a DB transaction; iterate over secrets,
  encrypt each value via `crypto.Encrypt`, and upsert into
  `workspace_secrets` within the same tx — rollback both on any failure
- Add `mock.ExpectBegin()`/`mock.ExpectCommit()`/`mock.ExpectRollback()`
  to all existing Create tests that were missing transaction expectations
- Add 3 new tests: WithSecrets_Persists, SecretPersistFails_RollsBack,
  EmptySecrets_OK

Closes #545

Co-authored-by: Molecule AI Backend Engineer <backend-engineer@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:46:17 +00:00
molecule-ai[bot]
38b72e149d docs(competitors): downgrade Paperclip threat HIGH → MEDIUM (#581)
Deep-dive #571 (Competitive Intelligence, 2026-04-17) confirmed Paperclip
has no A2A protocol, no visual canvas, and no org-chart UI on roadmap.
Blocker dependencies are a single-process task-graph DAG, not inter-agent
coordination. Execution policies are budget ceilings only. The sole
capability gap vs Molecule AI is per-workspace budget limits (tracked #541).
Brand/framing threat ("zero-human companies") but not a technical substitute.

- docs/ecosystem-watch.md: threat_level high → medium, notable_changes
  updated with deep-dive conclusion
- docs/marketing/competitors.md: move Paperclip row from HIGH to MEDIUM
  table; update Watchlist escalation levels; add recently-changed entry

Closes #571

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:45:53 +00:00
Molecule AI Backend Engineer
42be12a30c fix(brand-monitor): patch CVE-2024-47081 in requests, escape mrkdwn in Slack digest
CVE-2024-47081: upgrade requests 2.32.3 → 2.33.1 (netrc credential leak).

Slack mrkdwn injection: post_digest() embedded raw tweet text into a
mrkdwn link label (<url|snippet>) without escaping, allowing a malicious
tweet containing <!channel> or a phishing <url|label> to inject verbatim.
Fix: add _escape_mrkdwn() helper (& → &amp;, < → &lt;, > → &gt;) and
apply to the snippet in post_digest(). post_mentions() was already safe
via _format_tweet_block(). New test: test_post_digest_mrkdwn_escaping_in_snippet.

65 tests, 100% coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 00:41:38 +00:00
molecule-ai[bot]
7d4954a3b2 docs(devrel): Fly Machines provisioner tutorial (feat #501, closes #525) 2026-04-17 00:40:46 +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]
ed81fb6857 docs(blog): deploy anywhere — Fly Machines + control plane provisioners
Closes #561
2026-04-17 00:38:06 +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
molecule-ai[bot]
8eb6cd313f docs(devrel): Google ADK runtime tutorial (feat #550) 2026-04-17 00:30:49 +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