molecule-core/platform/internal/handlers
Molecule AI Backend Engineer 3bcb2b21a5 feat(platform): Cloudflare Artifacts demo integration (#595)
Add a minimal but complete integration with the Cloudflare Artifacts API
(private beta Apr 2026, public beta May 2026) — "Git for agents" versioned
workspace-snapshot storage.

## What's included

**`platform/internal/artifacts/client.go`** — typed Go HTTP client for the
CF Artifacts REST API:
- CreateRepo, GetRepo, ForkRepo, ImportRepo, DeleteRepo
- CreateToken, RevokeToken
- CF v4 response-envelope decoding; *APIError with StatusCode + Message

**`platform/internal/handlers/artifacts.go`** — four workspace-scoped
Gin handlers (all behind WorkspaceAuth middleware):
- POST /workspaces/:id/artifacts — attach or import a CF Artifacts repo
- GET  /workspaces/:id/artifacts — get linked repo info (DB + live CF)
- POST /workspaces/:id/artifacts/fork — fork the workspace's repo
- POST /workspaces/:id/artifacts/token — mint a short-lived git credential

**`platform/migrations/028_workspace_artifacts.up.sql`** — `workspace_artifacts`
table: one-to-one link between a workspace and its CF Artifacts repo.
Credentials are never stored; only the credential-stripped remote URL.

**`platform/internal/router/router.go`** — wire the four routes into the
existing wsAuth group.

## Configuration
Two env vars gate the feature (returns 503 when either is absent):
- CF_ARTIFACTS_API_TOKEN — Cloudflare API token with Artifacts write perms
- CF_ARTIFACTS_NAMESPACE — Cloudflare Artifacts namespace name

## Tests
- 10 client-level tests (httptest.Server + CF v4 envelope mocks)
- 14 handler-level tests (sqlmock DB + mock CF server)
- Helper unit tests for stripCredentials, cfErrToHTTP

All 21 packages pass (go test ./...).

Closes #595

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 06:28:58 +00:00
..
a2a_proxy_test.go test: 100% coverage of extracted helpers + ConfirmDialog singleButton 2026-04-13 17:08:33 -07:00
a2a_proxy.go fix(issue-541): correct stale 429 comment to 402 in checkWorkspaceBudget 2026-04-17 06:18:41 +00:00
activity_test.go test: 100% coverage of extracted helpers + ConfirmDialog singleButton 2026-04-13 17:08:33 -07:00
activity.go fix(security): #234 — sanitize source_id spoof log line via %q 2026-04-15 12:04:26 -07:00
admin_test_token_test.go feat(platform): GET /admin/workspaces/:id/test-token for E2E (#6) 2026-04-14 09:35:26 -07:00
admin_test_token.go feat(platform): GET /admin/workspaces/:id/test-token for E2E (#6) 2026-04-14 09:35:26 -07:00
agent_git_identity_test.go feat(provisioner): per-agent git identity via GIT_AUTHOR_* env vars 2026-04-16 00:45:26 -07:00
agent_git_identity.go feat(provisioner): per-agent git identity via GIT_AUTHOR_* env vars 2026-04-16 00:45:26 -07:00
agent_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
agent.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
approvals_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
approvals.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
artifacts_test.go feat(platform): Cloudflare Artifacts demo integration (#595) 2026-04-17 06:28:58 +00:00
artifacts.go feat(platform): Cloudflare Artifacts demo integration (#595) 2026-04-17 06:28:58 +00:00
budget_test.go feat(#541): add dedicated GET/PATCH /workspaces/:id/budget endpoints 2026-04-17 06:18:41 +00:00
budget.go feat(#541): add dedicated GET/PATCH /workspaces/:id/budget endpoints 2026-04-17 06:18:41 +00:00
bundle.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
channels_test.go feat(channels): per-channel message budget with 429 enforcement (#368) 2026-04-16 11:17:14 +00:00
channels.go feat(channels): per-channel message budget with 429 enforcement (#368) 2026-04-16 11:17:14 +00:00
config_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
config.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
container_files.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
delegation_test.go fix(platform): reject self-delegation to prevent _run_lock deadlock (#570) 2026-04-17 00:46:20 +00:00
delegation.go fix(platform): reject self-delegation to prevent _run_lock deadlock (#570) 2026-04-17 00:46:20 +00:00
discovery_test.go test: 100% coverage of extracted helpers + ConfirmDialog singleButton 2026-04-13 17:08:33 -07:00
discovery.go chore: quality pass — native dialogs, env sync, Go handler splits 2026-04-13 14:36:30 -07:00
events_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
events.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
github_token_test.go fix(github): refresh installation token when TTL < 10 min (#547) (#567) 2026-04-17 00:47:03 +00:00
github_token.go fix(github): refresh installation token when TTL < 10 min (#547) (#567) 2026-04-17 00:47:03 +00:00
handlers_additional_test.go feat(platform): add per-workspace budget_limit field and A2A enforcement (#541) 2026-04-17 06:18:41 +00:00
handlers_extended_test.go test(security): add #120 regression tests — PATCH auth + workspace existence guard 2026-04-15 08:40:06 +00:00
handlers_test.go feat(platform): add per-workspace budget_limit field and A2A enforcement (#541) 2026-04-17 06:18:41 +00:00
memories_test.go fix(memories): add hard cap of 50 on recall results (#377) 2026-04-16 11:12:35 +00:00
memories.go fix(memories): add hard cap of 50 on recall results (#377) 2026-04-16 11:12:35 +00:00
memory_test.go feat(memory): optimistic-locking via if_match_version on workspace_memory writes 2026-04-16 02:32:46 -07:00
memory.go feat(memory): optimistic-locking via if_match_version on workspace_memory writes 2026-04-16 02:32:46 -07:00
org_include_test.go feat(org-templates): Phase 4 — atomize each role to <role>/workspace.yaml 2026-04-16 03:09:56 -07:00
org_include.go feat(org-templates): Phase 4 — atomize each role to <role>/workspace.yaml 2026-04-16 03:09:56 -07:00
org_path_test.go fix(security): #103 — path-sanitize + admin-gate POST /org/import 2026-04-15 00:18:09 -07:00
org_plugin_allowlist_test.go feat(platform): per-org plugin governance registry (#591) 2026-04-17 05:40:23 +00:00
org_plugin_allowlist.go feat(platform): per-org plugin governance registry (#591) 2026-04-17 05:40:23 +00:00
org_prompt_ref_test.go feat(org-templates): Phase 1 — externalize prompt bodies to sibling files (#389) 2026-04-16 00:32:09 -07:00
org_test.go fix(org): use yaml.Marshal for category_routing + newline-guard block appends 2026-04-14 14:28:22 -07:00
org.go fix(platform): unblock org-template imports against modular workspace templates 2026-04-16 07:49:45 -07:00
plugins_install_pipeline_test.go test(handlers): add unit test suite for plugins_install_pipeline.go 2026-04-15 18:47:25 +00:00
plugins_install_pipeline.go refactor(platform): split 981-line plugins.go into per-domain modules 2026-04-13 18:01:59 -07:00
plugins_install.go feat(platform): per-org plugin governance registry (#591) 2026-04-17 05:40:23 +00:00
plugins_listing.go refactor(platform): split 981-line plugins.go into per-domain modules 2026-04-13 18:01:59 -07:00
plugins_sources.go refactor(platform): split 981-line plugins.go into per-domain modules 2026-04-13 18:01:59 -07:00
plugins_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
plugins.go refactor(platform): split 981-line plugins.go into per-domain modules 2026-04-13 18:01:59 -07:00
registry_test.go fix(security): registry DB errors must not leak raw driver messages (closes #435) 2026-04-16 10:34:35 +00:00
registry.go feat(platform): add per-workspace budget_limit field and A2A enforcement (#541) 2026-04-17 06:18:41 +00:00
restart_context_test.go feat(platform): inject restart context system message (#19 Layer 1) 2026-04-14 12:41:01 -07:00
restart_context.go feat(platform): inject restart context system message (#19 Layer 1) 2026-04-14 12:41:01 -07:00
schedules_test.go fix(#249): add /schedules/health endpoint accessible to CanCommunicate peers (#400) 2026-04-16 00:45:30 -07:00
schedules.go fix(#249): add /schedules/health endpoint accessible to CanCommunicate peers (#400) 2026-04-16 00:45:30 -07:00
secrets_test.go fix(secrets): auto-restart workspaces on global secret change (#15) 2026-04-14 12:39:00 -07:00
secrets.go fix(secrets): auto-restart workspaces on global secret change (#15) 2026-04-14 12:39:00 -07:00
socket.go fix(security): Cycle 5 — auth middleware, injection hardening, skill sandbox 2026-04-14 04:44:42 +00:00
sse_test.go feat(platform): AG-UI compatible SSE endpoint for streaming agent events (#590) 2026-04-17 05:16:51 +00:00
sse.go feat(platform): AG-UI compatible SSE endpoint for streaming agent events (#590) 2026-04-17 05:16:51 +00:00
team_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
team.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
template_import_test.go fix(security): #221 — quote name as YAML scalar instead of stripping newlines 2026-04-15 11:58:16 -07:00
template_import.go fix(security): YAML-quote skill/prompt names in generateDefaultConfig + opaque file-write errors 2026-04-16 05:40:45 -07:00
templates_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
templates.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
terminal.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
tokens_test.go feat(platform): token management API + MCP setup + external agent guide 2026-04-16 08:37:42 -07:00
tokens.go fix: code review findings — dead code, DRY, rate limit, docs 2026-04-16 12:04:37 -07:00
traces_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
traces.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
transcript_test.go fix(security): forward Authorization header in transcript proxy (#405) (#380) 2026-04-15 23:38:07 -07:00
transcript.go fix(security): forward Authorization header in transcript proxy (#405) (#380) 2026-04-15 23:38:07 -07:00
viewport_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
viewport.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
webhooks_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
webhooks_workflow_test.go feat(webhooks): #101 — workflow_run event → DevOps A2A 2026-04-15 00:25:49 -07:00
webhooks.go feat(webhooks): #101 — workflow_run event → DevOps A2A 2026-04-15 00:25:49 -07:00
workspace_budget_test.go fix(migrations): renumber budget migration 025→027 to follow gap fix (#631) 2026-04-17 06:22:09 +00:00
workspace_metrics_test.go feat(platform): per-workspace token tracking + GET /workspaces/:id/metrics (#593) 2026-04-17 05:29:10 +00:00
workspace_metrics.go feat(platform): per-workspace token tracking + GET /workspaces/:id/metrics (#593) 2026-04-17 05:29:10 +00:00
workspace_provision_test.go fix(auth): inject fresh bearer token into config volume on every provision (closes #418) 2026-04-16 05:26:10 -07:00
workspace_provision.go fix: code review findings — dead code, DRY, rate limit, docs 2026-04-16 12:04:37 -07:00
workspace_restart_test.go initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
workspace_restart.go fix(provisioner): rebuild_config flag on restart recovers from destroyed config volume (closes #239) 2026-04-16 10:34:25 +00:00
workspace_test.go fix(migrations): renumber budget migration 025→027 to follow gap fix (#631) 2026-04-17 06:22:09 +00:00
workspace.go fix(#611): remove budget_limit from PATCH /workspaces/:id and strip financial fields from GET 2026-04-17 06:18:41 +00:00