Commit Graph

1331 Commits

Author SHA1 Message Date
Molecule AI Community Manager
2f66f8f8cd docs(tutorials): add Social Channels Quickstart
Parallel Discord + Telegram setup guide, ~10 min to slash-command bot.
Companion to Discord adapter launch. Cross-links Lark tutorial, social-channels.md,
remote-agent tutorial.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:52:13 +00:00
Molecule AI Community Manager
6322e91873 docs(marketing): update Discord adapter posting guide — Day 2 prep
- Add Reddit r/LocalLlama + r/MachineLearning copy sources
- Add full Hacker News post body + guidelines
- Add dev.to full post body + frontmatter
- Add Discord server #announcements copy
- Add coordination checklist with [BLOG_URL] placeholder flag
- Update PR/status references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:50:24 +00:00
molecule-ai[bot]
e26e542888
fix(docs): correct platform and canvas domains in org-scoped API keys blog post
platform.moleculeai.ai -> platform.moleculesai.app
canvas.moleculeai.ai -> canvas.moleculesai.app

Spotted during docs PR review cycle.
2026-04-21 11:42:15 +00:00
eaadf72e2d fix(test): resolve 4 compile errors in workspace_provision_test.go
Issue #1366: Handlers test package broken on main.

Changes:
- Wrap orphaned largeContent declarations in
  TestSeedInitialMemories_ContentOverLimit (was outside any function)
- ExpectExpectations → ExpectationsWereMet (3 occurrences, sqlmock API)
- mockEnvMutator.Register(interface{}) → Register(provisionhook.EnvMutator)
  to match pkg/provisionhook Registry.Register signature
- mockResolver missing Scheme() method (SourceResolver interface req)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:39:48 +00:00
Molecule AI Community Manager
657d07a3d8 docs(assets): add Discord adapter hero image for Day 2 campaign
1200×630 PNG, Discord dark theme, slash command /ask flow.
Companion asset for Discord adapter announcement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:38:34 +00:00
Molecule AI Community Manager
b95421609a docs(audio): add TTS narration for audit chain verification explainer
94s MP3 narration + script for HMAC audit ledger blog post.
Companion audio asset.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:22:03 +00:00
molecule-ai[bot]
1e6d66c6ae
fix(tests): resolve all compaction artefacts in handlers test package (#1366)
- ExpectExpectations -> ExpectationsWereMet (3 occurrences)
- Add Scheme() to mockResolver (satisfies plugins.SourceResolver interface)
- Wrap orphan largeContent in TestSeedInitialMemories_Truncation
2026-04-21 11:21:26 +00:00
molecule-ai[bot]
cc290c3255
fix(tests): add org_id to orgTokenValidateQuery mock — Validate reads 3 columns (#1366) 2026-04-21 11:20:37 +00:00
molecule-ai[bot]
8dde18bc61
fix(tests): add orgID to Validate unpack — Validate returns 4 values (#1366) 2026-04-21 11:19:59 +00:00
molecule-ai[bot]
00bd73f8c8
fix(canvas): a11y fixes + budget_used TypeScript guard + orgs-page test fix (#1367)
* fix(canvas/a11y): mark StatusDot as aria-hidden — decorative element

StatusDot is purely decorative; the status is already conveyed via
aria-label on parent elements (WorkspaceNode, SidePanel header, etc.).
Marking it aria-hidden="true" prevents screen readers from announcing
the empty div as "img" with no alt text.

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

* fix(canvas): guard budget_used optional field with ?? 0 in progress calc

TypeScript error in CI: 'budget.budget_used' is possibly 'undefined'
when used in the progress percentage calculation. The field is
optional per BudgetData interface, so ?? 0 is the correct guard.

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

* fix(canvas/a11y): Tooltip keyboard focus support + ARIA role

- Add role="tooltip" + unique id so assistive tech can find tooltip content
- Add aria-describedby on trigger so screen readers announce tooltip text
- Add onFocus/onBlur handlers so keyboard users (Tab navigation) can see
  tooltips that mouse users see on hover

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

* fix(canvas/test): restore advanceTimersByTime pattern in orgs-page error test

waitFor() + fake timers (vi.useFakeTimers in beforeEach) cause race
conditions: the 5s polling timeout fires before React state updates flush.
Restores the established pattern used by all other tests in this file:
advanceTimersByTimeAsync(50) + runAllTimersAsync().
Also removes the now-unused waitFor import.

Ref: PRs #1360, #1345
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Molecule AI Core-UIUX <core-uiux@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:08:24 +00:00
Molecule AI Community Manager
e20ec33d33 docs(blog): add audit chain verification explainer
HMAC-SHA256 immutable ledger architecture + PR #1339 panic fix.
Companion to org-scoped API keys post. Enterprise/compliance audience.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:08:01 +00:00
Molecule AI Community Manager
9ef87a4f1e docs(devrel): add Phase 30 hero video — 3 aspect ratio cuts
Primary (16:9), social (9:16), and LinkedIn (1:1) cuts.
47.95s, 30fps H.264, dark zinc theme, burn-in captions, VO track.

Assembled from:
- marketing/assets/phase30-fleet-diagram.png
- marketing/audio/phase30-video-vo.mp3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:04:27 +00:00
molecule-ai[bot]
c886b528a4
fix(incidents): redact credential prefix/suffix in INCIDENT_LOG.md (GH #1333) (#1359)
Reduces credential surface in INCIDENT_LOG.md from partial-informative
(kvv-lHt-QFSyZwxeo...KVw, github_pat_11BPRRWQI0m...hsIJLIL) to
fully-redacted (sk-cp-lHt...KVw, github_pat_11...hsIJLIL) format.

ADMIN_TOKEN was already in truncated form (HlgeMb8...ShARE=).

Addresses GH #1333.

Co-authored-by: Molecule AI Core-DevOps <core-devops@agents.moleculesai.app>
2026-04-21 10:32:23 +00:00
Molecule AI Community Manager
8adf972dd9 docs(tutorials): add Self-Hosted AI Agents deployment guide
Covers Docker, Fly Machines, and bare metal deployment models with
use cases, configuration examples, and a comparison table. Captures
keywords from SEO brief #1126: self-hosted AI agents platform, remote
AI agent deployment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 10:26:41 +00:00
Molecule AI Community Manager
dbf53aa901 docs(marketing): add Discord adapter Day 2 Reddit/HN campaign copy
Adds Reddit (r/LocalLLaMA) and Hacker News post bodies for Discord adapter
Day 2 community campaign. Blog URL left as placeholder — fill before posting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 10:26:14 +00:00
molecule-ai[bot]
3ed1201d74
Merge pull request #1358 from Molecule-AI/content/blog/org-scoped-api-keys-v4
docs(blog): add org-scoped API keys enterprise key management post
2026-04-21 08:27:16 +00:00
molecule-ai[bot]
274a0b6727
docs(blog): add org-scoped API keys enterprise key management post
Adds the org-scoped API keys blog post (extracted from orphaned PR #1342).
Already live on Molecule-AI/docs main at content/blog/2026-04-20-org-api-keys.
Molecule AI is open source. Org-scoped API keys shipped in PRs #1105, #1107, #1109, and #1110.
2026-04-21 08:26:50 +00:00
molecule-ai[bot]
bde456a893 feat(canvas/e2e): add Playwright test for context-menu → delete confirm flow (#1344)
Issue #1138: Add Playwright E2E for context-menu → delete confirm flow.

The unit test (ContextMenu.keyboard.test.tsx) only exercises the store
setter — it can't catch the portal/race bug from PR #1133 where the
portal-rendered ConfirmDialog was closed by the menu's outside-click
handler before onConfirm fired.

This E2E test covers:
- Right-click workspace node → context menu opens
- Click Delete → ConfirmDialog appears (not swallowed)
- Click Confirm → dialog closes, node disappears, DELETE /workspaces/:id fires
- Click Cancel → dialog closes, node remains

Requires: platform on :8080, canvas on :3000.

Closes #1138.

Co-authored-by: Molecule AI Core-UIUX <core-uiux@agents.moleculesai.app>
2026-04-21 08:11:48 +00:00
molecule-ai[bot]
3bef6af241 fix: apply #1124 env-var defaults + scrub F1088 credentials from INCIDENT_LOG.md (#1347)
- PLATFORM_URL: replace unreachable http://platform:8080 mesh-only default
  with Docker-aware detection (host.docker.internal in containers,
  localhost for local dev) across all workspace Python modules and the
  git-token-helper shell script.
- WORKSPACE_ID: add fail-fast validation in main.py (SystemExit if empty)
  consistent with coordinator.py / a2a_cli.py patterns already in place.
- INCIDENT_LOG.md: replace all 3 F1088 credential types with
  ***REDACTED*** (sk-cp- 2x, github_pat_ 2x, ADMIN_TOKEN base64 3x).

Fixes #1124, #1333.

Co-authored-by: Molecule AI Dev Lead <dev-lead@agents.moleculesai.app>
2026-04-21 08:11:44 +00:00
molecule-ai[bot]
f2e4f71fee fix(canvas/test): restore waitFor in orgs-page error test + add getState mock (#1341)
Issue #1268: orgs-page error state test — replace vi.advanceTimersByTimeAsync(50)
with waitFor polling. advanceTimersByTimeAsync fires the timer but does not
guarantee React render flush completes before the assertion runs.

Issue #1269: ContextMenu keyboard test — add getState: () => mockStore to
useCanvasStore mock. PR #1243 changed the delete flow to hoist confirmation
to Canvas-level dialog via setPendingDelete, which reads .nodes via
useCanvasStore.getState() — the mock was missing getState.

Also carries forward the Issue #1124 WORKSPACE_ID fail-fast fix from
workspace/ modules (a2a_cli, a2a_client, coordinator, consolidation,
molecule_ai_status) — RuntimeError if WORKSPACE_ID is unset/empty.

Co-authored-by: Molecule AI Core Platform Lead <core-platform-lead@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:52:15 +00:00
molecule-ai[bot]
012f64e488 fix: guard HMAC slice truncation in audit chain verification (fixes #1332) (#1339)
ev.HMAC[:12] panics when HMAC is shorter than 12 bytes.
Add len guards before truncation so the log line never panics —
the mismatch is still reported, just with whatever prefix is available.

Co-authored-by: Molecule AI Infra-SRE <infra-sre@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:52:11 +00:00
molecule-ai[bot]
9fe593eed0 fix(container_files): remove duplicate ContainerWait loop in deleteViaEphemeral (#1334) (#1337)
* fix(canvas/test): restore test regressions from PR #1243

PR #1243 introduced two regressions in the canvas vitest suite:

1. ContextMenu.keyboard.test.tsx: the setPendingDelete call now
   passes `{hasChildren, id, name}` (not just `{id, name}`). Updated
   the keyboard-a11y test assertion to match the new store shape.

2. orgs-page.test.tsx: mockFetch.mockResolvedValueOnce() returned a
   plain object that didn't match the two-argument (url, options)
   call signature used by the component's fetch wrapper. Switched to
   mockImplementationOnce returning a rejected Promise — matching
   real fetch's rejection contract — and added runAllTimersAsync after
   advanceTimersByTimeAsync(50) to flush React state updates.

54 test files · 813 tests · all passing

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

* fix(canvas): replace bounding-box intersection with distance threshold for nest detection

ReactFlow's getIntersectingNodes uses bounding-box overlap detection, which
fires the drag-over state whenever any part of two nodes' position rectangles
overlap — even when the dragged node is far from the target. This made the
"Nest Workspace" dialog appear from large distances.

Fix: scan all nodes on each drag tick and set dragOverNodeId to the closest
node within NEST_PROXIMITY_THRESHOLD (150 px, center-to-center). This matches
the intuitive behavior: nest only when the node is actually dropped near another.

Constants:
- NEST_PROXIMITY_THRESHOLD = 150px (~60% of a collapsed node's width)
- DEFAULT_NODE_WIDTH = 245px (mid-range of min/max node widths)
- DEFAULT_NODE_HEIGHT = 110px

Also removed the unused getIntersectingNodes import (was causing duplicate
identifier error when both onNodeDrag and the zoom handler called useReactFlow
in the same component scope).

Closes #1052.

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

* fix(canvas): cascade-delete UX — show child count and require checkbox before Delete All

Issue #1137: with ?confirm=true always sent, a single confirmation silently
cascades — a team lead with 20 children gets nuked on one click.

Changes:
- store/canvas.ts: pendingDelete type now includes children: {id, name}[]
- ContextMenu.tsx: passes child list to setPendingDelete on Delete click
- DeleteCascadeConfirmDialog.tsx: new component — shows child names, a
  cascade warning, and requires the operator to tick a checkbox before
  Delete All activates. Disabled by default; only enables after checkbox.
- Canvas.tsx: conditionally renders DeleteCascadeConfirmDialog for
  hasChildren workspaces, or plain ConfirmDialog for leaf workspaces.
  confirmDelete requires cascadeConfirmChecked=true when hasChildren.
- ContextMenu.keyboard.test.tsx: updated setPendingDelete assertion to
  include children:[] (no children in the test fixture).

813 tests pass.

Closes #1137.

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

* fix(container_files): remove duplicate ContainerWait loop in deleteViaEphemeral

Issue #1334: Staging HEAD c90ada3 (PR #1328) left two identical
ContainerWait loops in deleteViaEphemeral. The first loop always
returns before the second executes — the second is unreachable dead
code. Remove it.

No functional change (the remaining loop handles the wait correctly).

---------

Co-authored-by: Molecule AI Core-UIUX <core-uiux@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:42:08 +00:00
molecule-ai[bot]
e07e22ad57 fix(orchestrator): fail-fast if WORKSPACE_ID env var is unset/empty (#1124) (#1336)
* fix(orchestrator): fail-fast if WORKSPACE_ID env var is unset/empty

Issue #1124: orchestrator GET /workspaces/{WORKSPACE_ID} returned 404
because 5 Python modules defaulted WORKSPACE_ID to "" instead of
validating the injected value. Empty string produced URLs like
/workspaces//heartbeat — route not found.

Fix: raise RuntimeError at module load if WORKSPACE_ID is unset
or empty, rather than silently producing broken API calls downstream.

Files changed (all same pattern):
- workspace/a2a_cli.py
- workspace/a2a_client.py
- workspace/coordinator.py
- workspace/consolidation.py
- workspace/molecule_ai_status.py

The platform (provisioner.go:375) correctly injects WORKSPACE_ID at
container provision time. This fix ensures the orchestrator surfaces
the misconfiguration immediately instead of failing silently at runtime.

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

* docs(incidents): rebuild INCIDENT_LOG — linter reset, all sections restored

Rebuilt after linter reset. Sections restored:
- Security Audit Cycle 6 (abc58b47)
- F1100 workspace_restart.go path traversal (resolved via 0bd2bf2)
- F1088 credential exposure (closed)
- F1097 org_id context fix (resolved)
- PR #1226 err.Error() leaks (stale)
- QA Round 18 orgs-page regression (fixed on main, staging pending)
- Issue #1124 fix PR #1336 filed

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

---------

Co-authored-by: Molecule AI Core Platform Lead <core-platform-lead@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:42:00 +00:00
molecule-ai[bot]
c90ada34ac fix(container_files.go): add validateRelPath definition + CWE-78 exec form (#1328)
Issue #1317: validateRelPath was called in deleteViaEphemeral but
never defined — staging dc21821 would fail Go build if CI completed.

Changes:
- Add validateRelPath function (filepath.Clean + abs/traversal guard)
  matching the pattern used on main (PR #1310).
- Upgrade deleteViaEphemeral to exec form ([]string{...}) so filePath
  is passed as a plain argument, not interpolated into a shell string.
  This eliminates shell injection (CWE-78) entirely.
- Add ContainerWait loop to guarantee rm completes before container
  removal (avoids race on fast delete vs container-stop).

Co-authored-by: Molecule AI Infra-Runtime-BE <infra-runtime-be@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:28:36 +00:00
molecule-ai[bot]
5a219436f4 docs(incidents): update INCIDENT_LOG — all findings re-verified post-restart (#1326)
- F1088: Close reminder added (admin token rotation still recommended)
- CI stall: RESOLVED — staging CI progressing normally (run #24708961892 success)
- PR #1246: Superseded by PR #1247 (732f65e, merged to main — sed fix done)
- CWE-78 branch: Superseded by dc21821 (staging) and 169120d (main) — proper fixes merged
- CWE-918 SSRF: e431fc4 merged to main
- F1085 regression branch: Still a regression (behind staging, removes redactSecrets)
- Issue #1124: Root cause confirmed — 5 Python modules default WORKSPACE_ID to ""; fail-fast fix documented

Co-authored-by: Molecule AI Core Platform Lead <core-platform-lead@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:21:30 +00:00
molecule-ai[bot]
c0d5e528a4 fix(canvas): cascade-delete UX — require checkbox before Delete All (#1314)
* fix(canvas/test): restore test regressions from PR #1243

PR #1243 introduced two regressions in the canvas vitest suite:

1. ContextMenu.keyboard.test.tsx: the setPendingDelete call now
   passes `{hasChildren, id, name}` (not just `{id, name}`). Updated
   the keyboard-a11y test assertion to match the new store shape.

2. orgs-page.test.tsx: mockFetch.mockResolvedValueOnce() returned a
   plain object that didn't match the two-argument (url, options)
   call signature used by the component's fetch wrapper. Switched to
   mockImplementationOnce returning a rejected Promise — matching
   real fetch's rejection contract — and added runAllTimersAsync after
   advanceTimersByTimeAsync(50) to flush React state updates.

54 test files · 813 tests · all passing

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

* fix(canvas): replace bounding-box intersection with distance threshold for nest detection

ReactFlow's getIntersectingNodes uses bounding-box overlap detection, which
fires the drag-over state whenever any part of two nodes' position rectangles
overlap — even when the dragged node is far from the target. This made the
"Nest Workspace" dialog appear from large distances.

Fix: scan all nodes on each drag tick and set dragOverNodeId to the closest
node within NEST_PROXIMITY_THRESHOLD (150 px, center-to-center). This matches
the intuitive behavior: nest only when the node is actually dropped near another.

Constants:
- NEST_PROXIMITY_THRESHOLD = 150px (~60% of a collapsed node's width)
- DEFAULT_NODE_WIDTH = 245px (mid-range of min/max node widths)
- DEFAULT_NODE_HEIGHT = 110px

Also removed the unused getIntersectingNodes import (was causing duplicate
identifier error when both onNodeDrag and the zoom handler called useReactFlow
in the same component scope).

Closes #1052.

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

* fix(canvas): cascade-delete UX — show child count and require checkbox before Delete All

Issue #1137: with ?confirm=true always sent, a single confirmation silently
cascades — a team lead with 20 children gets nuked on one click.

Changes:
- store/canvas.ts: pendingDelete type now includes children: {id, name}[]
- ContextMenu.tsx: passes child list to setPendingDelete on Delete click
- DeleteCascadeConfirmDialog.tsx: new component — shows child names, a
  cascade warning, and requires the operator to tick a checkbox before
  Delete All activates. Disabled by default; only enables after checkbox.
- Canvas.tsx: conditionally renders DeleteCascadeConfirmDialog for
  hasChildren workspaces, or plain ConfirmDialog for leaf workspaces.
  confirmDelete requires cascadeConfirmChecked=true when hasChildren.
- ContextMenu.keyboard.test.tsx: updated setPendingDelete assertion to
  include children:[] (no children in the test fixture).

813 tests pass.

Closes #1137.

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

---------

Co-authored-by: Molecule AI Core-UIUX <core-uiux@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:06:45 +00:00
molecule-ai[bot]
ae2ec74889 Merge pull request #1320 from Molecule-AI/fix/community-copy-pip-reddit
fix(community): correct pip package name + write Reddit post body
2026-04-21 07:06:22 +00:00
molecule-ai[bot]
1fca09152f fix(community): write Reddit post body in community-announcements.md 2026-04-21 07:05:58 +00:00
molecule-ai[bot]
7b3e1cbbac fix(community): pip install molecule-sdk → molecule-ai-sdk in HN launch guide 2026-04-21 07:05:57 +00:00
molecule-ai[bot]
ec09f86cee Merge pull request #1312 from Molecule-AI/fix/docs-url-typo-remote-workspaces-faq
fix(docs): correct https://wss:// mixed protocol typo in remote-workspaces-faq.md
2026-04-21 06:38:00 +00:00
molecule-ai[bot]
3dc5e83d6b fix(docs): correct https://wss:// mixed protocol typo in remote-workspaces-faq.md
Line 98 had 'curl -s https://wss://[your-org].moleculesai.app/health' —
mixed protocol prefix. Changed to 'curl -s https://' (HTTPS health check endpoint).

Spotted in PR #1276 review.
2026-04-21 06:37:25 +00:00
molecule-ai[bot]
dc218212be fix(security): CWE-22 path traversal in copyFilesToContainer and deleteViaEphemeral
CWE-22 fix:
- copyFilesToContainer: validate with filepath.Clean + IsAbs + strings.Contains(clean, '..'), use safeName for tar header
- deleteViaEphemeral: call validateRelPath(filePath) before constructing rm command
Fixes #1272
2026-04-21 06:32:11 +00:00
molecule-ai[bot]
cde02594bc Merge pull request #1306 from Molecule-AI/content/blog/phase30-launch-content
docs(marketing): Phase 30 launch — content blog posts, DevRel assets, and execution suite
2026-04-21 06:23:06 +00:00
molecule-ai[bot]
c40b237c32 docs(marketing): Phase 30 launch — content blog posts, DevRel assets, and execution suite
Rebuilt from original PR #1276. All Phase 30 launch content restored:
- 5 blog posts (Remote Workspaces, Chrome DevTools MCP, Container vs Remote, Secure by Design)
- 4 guides (Remote Workspaces, FAQ, same-origin canvas, quickstart audio)
- Community copy: Discord/Slack announcements, HN launch guide
- Social copy: Phase 30 (4 X versions + LinkedIn), Chrome DevTools MCP
- Sales: landing copy, battlecards, one-pager, objection handlers
- Press release draft
- Demos: AGENTS.md auto-gen, Cloudflare Artifacts
- Audio: TTS announce, VO scripts, demo narrations
- Fleet diagram, asset inventory, video production package
- Roadmap brief, email drip sequence, post-push checklist

Closes GH#1126
2026-04-21 06:22:27 +00:00
molecule-ai[bot]
aeb89994ef Merge pull request #1301 from Molecule-AI/content/blog/discord-adapter-launch
docs(blog): Discord adapter launch — Your AI Agents Just Joined Discord
2026-04-21 06:18:10 +00:00
molecule-ai[bot]
6331c5bfe8 docs(blog): Discord adapter launch — Your AI Agents Just Joined Discord 2026-04-21 06:11:39 +00:00
molecule-ai[bot]
966030037c seo: add Phase 30 Remote Workspaces keyword briefs (GH#1126) 2026-04-21 05:54:12 +00:00
molecule-ai[bot]
2e059b52a1 marketing: approve Fly.io Deploy Anywhere social copy — delayed push 2026-04-21 05:49:09 +00:00
molecule-ai[bot]
dc0c806db3 marketing: approve Chrome DevTools MCP social copy — post Day 1 today 2026-04-21 05:48:22 +00:00
molecule-ai[bot]
f52b6c3f64 fix(security): close F1086 err.Error() leaks in plugin install pipeline + provision (#1206)
* fix(plugins): close F1086 err.Error() leaks in plugin install pipeline

F1086 / #1206: Three err.Error() calls in the plugin install pipeline
leaked internal file paths, resolver state, and query parameters in API
responses. Replaced with context-appropriate generic messages:
- ParseSource error → "invalid plugin source"
- Resolve error → "plugin resolution failed" (available_schemes kept for
  self-service, raw error hidden)
- validatePluginName error → "invalid plugin name" (path traversal/injection
  risk means no diagnostic should be returned)

🤖 Generated with [Claude Code](https://claude.ai)

* fix(provision): close F1086 err.Error() leaks in workspace_provision.go

F1086 / #1206: env mutator and provisioner start errors in
workspace_provision.go leaked internal error strings (credential URIs,
docker/volume paths, AMI/VPC details) via:
- Broadcast payloads to canvas Events tab
- last_sample_error field in the workspaces DB row

Fixed all 6 occurrences across both the docker and CPProvisioner code paths:
- env mutator failures → "environment configuration failed"
- provisioner/docker start failures → "workspace start failed"

The verbose %v-logged errors are preserved for operator diagnostics;
only the broadcast and DB fields receive generic messages.

🤖 Generated with [Claude Code](https://claude.ai)

---------

Co-authored-by: Molecule AI Core-BE <core-be@agents.moleculesai.app>
2026-04-21 03:54:50 +00:00
molecule-ai[bot]
bfb5e16ae9 Merge pull request #1264 from Molecule-AI/fix/ci-cancel-in-progress-true
fix(ci): revert cancel-in-progress to true to restore CI operation
2026-04-21 03:42:44 +00:00
molecule-ai[bot]
23be5083e4 fix(ci): revert cancel-in-progress to true — ubuntu-runner dispatch stalled
With cancel-in-progress: false, pending CI runs accumulate in the
ci-staging concurrency group. New pushes create queued runs, but
GitHub dispatches multiple runs for the same SHA instead of replacing
the pending one. All runs get stuck/cancelled before completing.

Reverting to cancel-in-progress: true restores CI operation — runs
that are superseded are cancelled, freeing the concurrency slot for
the new run to proceed.

Runner availability (ubuntu-latest dispatch stall) is a separate
infra issue tracked independently.
2026-04-21 03:42:23 +00:00
Hongming Wang
1f35128ebb Merge pull request #1262 from Molecule-AI/fix/sweeper-emit-provision-failed
fix(sweeper): emit WORKSPACE_PROVISION_FAILED so canvas updates UI
2026-04-20 20:39:20 -07:00
Hongming Wang
ec52d155f4 fix(sweeper): emit WORKSPACE_PROVISION_FAILED so canvas updates UI
The provision-timeout sweeper was emitting a new WORKSPACE_PROVISION_TIMEOUT
event type, but the canvas event handler (canvas-events.ts:234) only
has a case for WORKSPACE_PROVISION_FAILED — the sweep's event fell
through silently. DB was being marked 'failed' but the UI stayed on
'starting' indefinitely until the user hard-refreshed.

Reusing the existing event name keeps the UI reaction uniform across
both fail paths (runtime-crash via bootstrap-watcher and boot-timeout
via sweeper). Operators who need to distinguish can read the `source`
payload field — "bootstrap_watcher" vs "provision_timeout_sweep".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:41 -07:00
molecule-ai[bot]
0bd2bf2b7f fix(security): CWE path-injection — resolveInsideRoot for Restart + ReadFile template paths (PR #1261)
workspace_restart.go:127-133 accepted body.Template (attacker-controlled)
via raw filepath.Join(h.configsDir, template), allowing path traversal
(e.g. "../../../etc") to escape configsDir.

Fix: replace raw filepath.Join with resolveInsideRoot, same pattern as
workspace.go:102 (already fixed) and workspace.go:249 (already fixed).
Both the explicit template path and the findTemplateByName fallback are
safe — findTemplateByName returns a directory name from os.ReadDir which
is inherently bounded and cannot contain "/".

On resolve error the template is cleared so findTemplateByName fallback
still fires (preserves existing restart behaviour when template is invalid).

Closes: #1043

Co-authored-by: Molecule AI Core-BE <core-be@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 03:38:39 +00:00
molecule-ai[bot]
7158f8f01c docs(blog): Skills Over Bundled Tools explainer (addresses issue #706) 2026-04-21 03:36:41 +00:00
molecule-ai[bot]
52709718ec fix(F1097): set org_id in Gin context for org-token callers (#1218) (#1258)
orgtoken.Validate now returns org_id (the org workspace UUID stored on
org_api_tokens rows, populated by #1212). Both call sites in
wsauth_middleware.go — WorkspaceAuth and AdminAuth — call
c.Set("org_id", orgID) after successful org-token validation.

This unbreaks orgCallerID(c) for org-token callers. Previously the
middleware populated org_token_id and org_token_prefix but never org_id,
so any handler reading c.Get("org_id") (e.g. requireCallerOwnsOrg) got
"" even for valid org tokens.

The change is additive: orgID may be empty for pre-migration tokens
minted before #1212. requireCallerOwnsOrg already handles empty org_id
by denying by default.

Co-authored-by: Molecule AI CP-BE <cp-be@agents.moleculesai.app>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 03:36:25 +00:00
molecule-ai[bot]
6fe3255eb5 docs(blog): Skills Over Bundled Tools explainer (addresses issue #706) 2026-04-21 03:34:29 +00:00
molecule-ai[bot]
217cdce306 Merge pull request #1254 from Molecule-AI/fix/ci-yml-yaml-v2
fix(ci): restore valid YAML in ci.yml after JSON-escape corruption
2026-04-21 03:27:34 +00:00
molecule-ai[bot]
bcf7f93281 fix(ci): restore valid YAML in ci.yml — correct concurrency + ubuntu runner
Root cause: commits e6d48e6 and e085621 stored ci.yml with JSON-escaped
content (literal \n sequences, leading double-quote) instead of proper
YAML with actual newlines. All CI runs failed with "workflow file issue"
before any job could start.

Fix: restore from pre-corruption base (2517164), apply intended changes:
- concurrency.cancel-in-progress: true → false (queue rather than cancel)
- changes job: runs-on ubuntu-latest (frees mac mini for real work)

PR #1242 intent preserved, corruption from API commit removed.
2026-04-21 03:27:06 +00:00