Makes the subprocess backend fully self-contained: each agent carries
its instructions, MCP servers, skills, and subagents in its
harness_config_json column, viewable in the Web UI, editable via CLI.
internal/harness/subprocess/config.go (NEW):
AgentConfig struct with optional fields:
- claude_md → workdir/CLAUDE.md
- agents_md → workdir/AGENTS.md
- mcp_servers → workdir/.mcp.json (Claude Code format)
- skills → workdir/.claude/skills/<name>/SKILL.md
- subagents → workdir/.claude/agents/<name>.md
- env → layered into child env (after k8s_env_json,
before caller overrides)
ParseAgentConfig tolerates empty / returns error on invalid JSON.
MaterialiseAgentConfig writes all artifacts into the workdir with
path-traversal sanitisation on skill/subagent names.
subprocess.Harness.Execute now calls Parse + Materialise before exec,
so an agent's declarative config is on disk by the time the child
CLI's cwd lookup fires. buildEnv takes the parsed config and overlays
cfg.Env on top of k8s_env_json.
Tests:
config_test.go — 6 cases: empty, invalid JSON, full round-trip,
materialise writes all artefacts, empty is a no-op, skill names
are sanitised against "../escape" / "/etc/passwd", mcp entries
without a name are dropped.
subprocess_test.go — 2 new e2e cases: agent with CLAUDE.md + mcp
servers + skills + env sees all of them from inside the child via
cat/echo; invalid harness_config_json surfaces as Execute error.
internal/agents/store.go:
AgentStore gains UpdateHarnessConfig(ctx, name, harnessName,
localCommand, harnessConfigJSON). Empty strings leave a field
unchanged; literal "-" clears (sets to NULL). Returns sql.ErrNoRows
on missing agent. AgentService exposes Store() so admin handlers
can reach it without adding a full service method for a
config-set-style operation.
store_test.go: 6-subcase test covers set-all, partial update, clear,
unknown agent, and no-field no-op.
internal/admin/socket.go:
Two new admin commands:
harness.config_get {agent_name} → {harness_name, local_command,
harness_config_json, harness_config (parsed), parse_error?}
harness.config_set {agent_name, harness_name?, local_command?,
harness_config_json?} → updated fields
config_set validates JSON shape before calling the store; null /
"-" literals clear the column.
cmd/synapbus/admin.go:
New top-level `harness config` command group:
synapbus harness config get --agent <name> [--raw]
synapbus harness config set --agent <name>
[--harness-name subprocess]
[--local-command '["claude","--print"]']
[--file config.json] # or pipe from stdin
[--clear]
synapbus harness config edit --agent <name>
# fetches current config, opens $VISUAL/$EDITOR/vi,
# validates JSON on save, writes back via config_set
web/src/routes/agents/[name]/+page.svelte:
New read-only "Harness" panel on the agent detail page:
- Resolved backend badge (explicit or inferred from k8s_image /
local_command / harness_config_json.url)
- Grid summary: CLAUDE.md size, AGENTS.md size, MCP server count,
skills count
- Collapsible details for CLAUDE.md, AGENTS.md, each MCP server
(name / type / url|command / header count), skill filenames,
subagent filenames, env vars
- Footer hint showing the CLI edit command
No edit controls — editing is CLI-only by design (safer, fits an
ops-heavy workflow).
Verified: full project test suite (40+ packages including integration
tests) plus `vite build` of the Svelte app all green; `go vet ./...`
clean; the existing TestSubprocess_Execute_MaterialisesHarnessConfig
e2e test proves the round-trip from harness_config_json → workdir →
child process works end-to-end.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 7: the reactor now branches on agent backend kind.
Reactor changes (internal/reactor/reactor.go):
* Adds `registry *harness.Registry` field + `SetHarnessRegistry`.
* `agentBackendKind()` picks k8s | subprocess | webhook | none from
the agent's `HarnessName`, `K8sImage`, `LocalCommand`, and
`HarnessConfigJSON` fields. Explicit `HarnessName` wins.
* `evaluateTrigger` applies the same preconditions (depth, daily
budget, cooldown, already-running, pending_work coalescing) to
every backend — a subprocess agent mentioned in a channel now
goes through the exact same rate limits a K8s agent does.
* K8s agents keep the existing `createJob` fast-return path with
the async poller for restart safety. Non-K8s agents use a new
`dispatchHarness` that inserts the reactive_runs row, spawns a
detached goroutine, blocks on `Registry.Execute`, and writes the
terminal status / error_log / metrics / failure DM on return.
* Import `harness`, `messaging`, `google/uuid` for building the
ExecRequest.
main.go wiring:
* Build one `harness.Registry` with all three real backends:
`k8sjob.New(k8sRunner, …)`, `subprocess.New(Config{BaseDir:
dataDir/harness/subprocess}, …)`, `webhook.New(Config{}, …)`.
* Attach a `runs.Store` as the registry Observer so every dispatch
writes a harness_runs row — no per-caller code required.
* Hand the registry to the reactor via `SetHarnessRegistry`.
* Log the registered backend names at startup.
Tests (internal/reactor/reactor_test.go):
* New `insertSubprocessAgent`, `newHarnessReactor`, `waitForRun`,
and `fakeNotifier` helpers.
* Seven new tests that register a stub harness under "subprocess"
and verify: success from @mention, failure recorded + DM sent,
depth-exceeded skipped, budget-exhausted skipped, cooldown
skipped, already-running queued, no-backend fails cleanly. Each
checks the harness stub is NOT called when a precondition skips.
* Existing `TestReactorNoK8sImage` keeps working — the old
k8s-specific error message is replaced with the backend-agnostic
"no backend configured" phrasing.
* `setupTestDB` now pins `SetMaxOpenConns(1)`: modernc.org/sqlite
in-memory DBs give each pool connection a fresh empty database,
which races the new dispatchHarness goroutine and main-test
goroutine. Pinning is the standard workaround.
The overall behaviour: `@local-agent` in a channel message now starts
the configured subprocess/webhook under the same depth/budget/cooldown
rate limits as a K8s agent, tracked in reactive_runs and harness_runs,
instrumented with an OTel span, with trace context propagated into the
child via env vars. Failure DMs go to the human owner, as with K8s.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces internal/harness — a minimal Harness interface inspired by
GoogleCloudPlatform/scion — plus four backends (k8sjob, subprocess,
webhook, stub) and an OTel-traced Registry that spans every dispatch
and injects W3C trace context into child processes via env vars.
Phases landed together on this branch:
1. internal/harness scaffold: Harness/Capabilities/ExecRequest/
ExecResult/Budget/Usage types, Registry with Resolve/Execute,
in-memory stub backend.
2. internal/harness/k8sjob: wraps existing k8s.JobRunner behind the
Harness interface with a Waiter abstraction (real clientset +
test fake). BuildHandler exports the per-agent config logic.
3. internal/harness/subprocess: os/exec-based backend (Mac+Linux),
per-run workdir, result.json handoff, bounded log capture,
Budget-driven wall-clock timeout.
4. internal/harness/webhook: synchronous HTTP POST with HMAC
signing via internal/webhooks.ComputeHMACSignature, per-agent
URL/secret/timeout read from harness_config_json.
5. internal/observability: OTel tracer init via OTLP HTTP (opt-in
via SYNAPBUS_OTEL_ENABLED), W3C propagator always installed;
Registry.Execute starts a harness.execute span per dispatch and
calls InjectTraceContext into req.Env so children inherit it.
6. internal/harness/runs: SQLite-backed Observer that persists a
harness_runs row per dispatch with status, usage, cost, duration,
trace_id, session_id, and a bounded logs excerpt.
Schema: new migration 019_harness.sql adds agents.harness_name /
local_command / harness_config_json columns and the backend-agnostic
harness_runs table with indices on (agent, created_at), (status),
(trace_id), (run_id). internal/reactor/reactor_test.go inline schema
updated to match.
Deployment: deploy/kubic/otel-collector.yaml stands up an otel-collector
Deployment + ConfigMap + ClusterIP Service in the synapbus namespace on
kubic, receiving OTLP gRPC (4317) and HTTP (4318) and exporting debug
output until a Tempo/Jaeger backend lands.
Docs: docs/harness-otel-research.html compares scion and paperclip
side-by-side and maps the current synapbus executor surface; its
companion docs/harness-otel-design.md carries the phase plan, span
taxonomy, and migration schema verbatim.
The reactor currently still calls k8s.JobRunner directly — rewiring it
through the Registry is a follow-up, intentionally out of scope for
this branch to keep the refactor reversible. The new packages are
independently tested (~78 new tests across 7 packages) and the full
project test suite passes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements US1, US2, and US3 of spec 016 by layering a marketplace service
on top of existing primitives rather than reinventing them:
- Capability manifests (US2) reuse the wiki subsystem. Each agent publishes
a per-agent article at slug "agent-<name>" and gets versioning, revision
history, and FTS search for free.
- Auction channels (US1) reuse the existing auction channel type, swarm
service, and task/bid store. post_auction / bid / award wrap post_task /
bid_task / accept_bid and attach marketplace metadata (max_budget_tokens,
domains, estimated_tokens, confidence, approach) in the task.requirements
and bid.capabilities JSON blobs. Award converts the auction into a claim
by DM'ing the winner at priority 8 with task_id metadata, so the existing
claim/process/done lifecycle takes over with zero new machinery.
- Reputation ledger (US3) adds migration 018_agent_marketplace.sql with a
new agent_reputation table keyed by (agent_name, domain). mark_task_done
completes the task via the swarm service and writes one ledger row per
declared domain using the reported actual_tokens and success_score.
query_reputation returns a rolled-up summary plus recent entries for a
given (agent, domain) pair — reputation is always a vector, never a
global score (FR-013).
Also:
- Adds the "awarded" reaction type (FR-008) alongside existing approve/
reject/in_progress/done/published. Migration 018 widens the reactions
CHECK constraint via a table rebuild.
- 6 new actions added to the action registry (post_auction, bid, award,
mark_task_done, read_skill_card, query_reputation) so the search tool
can discover them and the execute tool can dispatch them.
- New internal/marketplace package (store.go + service.go).
- New internal/mcp/marketplace.go bridge handlers.
- New internal/mcp/marketplace_test.go covers the full auction lifecycle,
capability manifest publish/read/update, self-bid rejection, non-auction
channel rejection, and reputation summary aggregation.
Out of scope for MVP (deferred per spec prompt): US4 reflection loop,
tombstoning FR-020a/b, multi-owner quorums, auto-escalation on zero bids,
bootstrap exploration credit, epsilon-greedy selection, and the hard-stop
budget enforcement daemon (only soft recording of estimated vs actual is
included).
All existing tests pass; new marketplace tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Trust scores: per (agent, action_type) pair, stored in agent_trust
table. Auto-adjusts when human reacts to AI agent messages (approve
+0.05, reject -0.1). Scores clamped [0.0, 1.0]. MCP get_trust action
+ REST API /api/trust/{agent}. Web UI shows trust progress bars on
agent detail pages.
Claim semantics: only one in_progress reaction per message enforced.
First agent to claim wins, duplicates rejected with clear error.
State-change webhooks: StateChangeNotifier interface fires
workflow.state_changed events through existing webhook infrastructure
when reactions change a message's derived workflow state.
Channel thresholds: publish_threshold and approve_threshold fields
on channels for configuring autonomy gates.
Migration 014_trust_claims.sql. 17 new test cases across trust
model + store.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add typed reactions (approve/reject/in_progress/done/published) with
toggle semantics. Workflow state derived from highest-priority reaction.
New reactions package with model, SQLite store, and service layer.
REST API: POST/GET/DELETE /api/messages/{id}/reactions for toggle/query,
PUT /api/channels/{name}/settings for workflow config, GET by-state
endpoint for listing messages by workflow state.
MCP: react/unreact/get_reactions/list_by_state actions via bridge.
Web UI: WorkflowBadge (colored state pills) and ReactionPills (toggle
pills with agent names) components integrated into channel view.
Channel settings: auto_approve, stalemate_remind_after,
stalemate_escalate_after columns. CLI: channels update command.
Migration 013_reactions.sql adds message_reactions table and channel
workflow columns. 29+ new test cases across model and store.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Web UI: paperclip button for file upload (images, PDFs, text), inline
attachment cards with file icon/name/size, image thumbnails with
fullscreen overlay, attachment display in thread panel.
Threads: always-visible reply count badges on messages, clickable to
open thread panel. reply_count and attachments enriched in all API
responses via batch queries.
MCP: attachments parameter on send_message tool, updated tool
descriptions for threading and attachment workflow guidance.
Backend: file type validation (allowlist), AttachmentLinker interface
to avoid circular deps, GetReplyCounts batch query, EnrichMessages
method on MessagingService.
Admin CLI: synapbus attachments backup/restore with tar.gz archives,
dedup-safe restore.
24 new test cases across 4 packages. All 24 test packages pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Analytics: time-series message graph with 5 time spans (1h/4h/24h/7d/30d),
top-5 agents and channels leaderboards, summary cards. 4 new REST endpoints.
PWA: web app manifest, service worker with cache-first static/network-only
API strategy, push notifications via Web Push API with VAPID keys, push
subscription management endpoints, SQLite migration for subscriptions.
UX fixes: auto-resize compose textarea (3-12 lines), inline editable agent
display name, editable human display name in settings, smart mention/channel
highlighting (existing→link, deleted→inactive badge, unknown→plain text),
font size -/+ preference (12-24px persisted in localStorage), version footer
with GitHub link.
MCP: 4 prompts — daily-digest, agent-health-check, channel-overview,
debug-agent. Registered with prompt capabilities enabled.
Code review fixes: scoped push unsubscribe to user, capped analytics limit
at 100, hardened HTML strip regex, bounded SW cache, backend push unsub on
disable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add public A2A Agent Card endpoint that exposes registered agents as skills
for cross-platform agent discovery. Includes admin CLI for updating agent
capabilities, which populate skill tags and descriptions in the card.
- internal/a2a: new package with AgentCard generator, HTTP handler, and tests
- agents store/service: add ListAllActiveAgents (excludes human accounts)
- admin socket: add agent.update_capabilities command
- admin CLI: add `agent update-capabilities --name --capabilities` subcommand
- main.go: register /.well-known/agent-card.json route (public, no auth)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Background worker that detects stale messages and takes corrective action:
- Auto-fails DMs stuck in "processing" after configurable timeout (default 24h)
- Sends system DM reminders for pending messages after ReminderAfter (default 4h)
- Escalates unprocessed messages to #approvals channel after EscalateAfter (default 48h)
- Deduplicates reminders and escalations to avoid spam
- Configurable via SYNAPBUS_STALEMATE_* environment variables
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Auto-join public channels on first send (bug #1)
- Channel broadcasts no longer create duplicate DM copies; inbox DMs
only sent for @mentions (bug #2)
- Embedding pipeline auto-enqueues new messages via MessageListener
callback instead of requiring pod restart (bug #3)
- Admin socket defaults to /tmp in containers to avoid PVC filesystem
incompatibility with Unix sockets (bug #5)
- SSE events now fire for MCP-sent messages (not just REST API),
enabling live notification badges without page reload
- Fixed frontend SSE field name mismatch (channel_name → channel)
- Fixed SSE client not connecting after login redirect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch Docker runtime from scratch to alpine:3.19 so kubectl exec works
for admin CLI operations. Add `synapbus channels create` and
`synapbus channels join` CLI commands with corresponding admin socket
handlers. Change default socket path to /data/synapbus.sock (absolute).
Also add Helm envFrom support and NodePort configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- JS/TS execution engine (goja + esbuild) with sandboxed runtime and call() bridge
- BM25 action discovery index over 23 registered actions
- ServiceBridge mapping call() invocations to existing service methods
- Admin CLI subcommands for webhook/k8s/gc operations
- Pagination support (offset/limit) in read_inbox, search_messages, get_channel_messages
- Fixed test assertions for call() envelope structure {ok, result}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 5 separate tool registrars (messaging, channels, swarm,
attachments, webhooks) with a single HybridToolRegistrar exposing
4 tools: my_status, send_message, search, and execute.
New foundation packages:
- internal/actions: action registry (22 actions) + BM25 search index
- internal/jsruntime: lightweight call() expression parser with
concurrency-limited execution pool
The `execute` tool dispatches call() expressions through a
ServiceBridge that maps action names to existing service methods,
preserving all original handler logic. The `search` tool enables
agents to discover available actions by keyword. The `send_message`
tool merges DM and channel sending with mutual exclusion.
All unit tests, integration tests, build, and vet pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `my_status` MCP tool: single call returns agent identity, pending
DMs, channel mentions, system notifications, channel summaries, and
stats with truncation for large inboxes
- Add embeddings CLI: `synapbus embeddings status|reindex|clear` for
managing vectors when switching embedding providers
- Add automatic message retention worker with configurable period
(--message-retention, default 12m), warning notifications 1 month
before deletion, cascade cleanup, and incremental vacuum
- Add manual purge: `synapbus messages purge --older-than --agent --channel`
and `synapbus db vacuum` for on-demand cleanup
- Add `synapbus retention status` CLI for admin visibility
- Create system agent at startup for sending retention warnings
- Filter system agent from discover_agents results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix leave channel: handle ErrOwnerCannotLeave with error display, remove
all owned agents from channel
- Close thread panel when navigating between channels/DMs
- Remove Type dropdown from agent registration (agents are always AI;
human accounts created via CLI)
- Fix dashboard showing "Untitled conversation" — now shows last agent name
- Fix "1 msgs" → "1 msg" singular form on dashboard
- Fix conversation detail "-- N messages" → "— N message(s)" with em-dash
- Hide "done" status badge in MessageList and conversation detail
(consistent with DM view behavior)
- Add thread reply buttons and reply count to channel and DM messages
- Add agent selector for multi-agent users in channel and DM compose
- Add "Join Channel" prompt for non-members in channel compose area
- Show "(you)" indicator on channel member list for owned agents
- Add agent detail page with messages endpoint
- Improve release workflow and Dockerfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move module path from github.com/smart-mcp-proxy/synapbus to
github.com/synapbus/synapbus across all Go imports (47 files).
Add constellation logo options generated via FLUX 1.1 Pro.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add specification for production readiness & website launch
Covers DevOps hooks, CI/CD, Prometheus observability, Docker/Helm
deployment, and synapbus.dev website with documentation and blog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add implementation plan and research for production readiness
Covers 5 workstreams: git hooks, CI/CD, observability, deployment
artifacts, and website. All constitution gates pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add pre-commit and pre-push git hooks
Pre-commit runs go vet, golangci-lint (optional), and fast tests.
Pre-push runs full test suite and build verification.
Installable via `make hooks`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: add GitHub Actions for PR checks and releases
ci.yml: lint, test, build on PRs to main.
release.yml: multi-platform binaries + Docker image on version tags.
Targets: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64.
Docker pushed to ghcr.io/smart-mcp-proxy/synapbus.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Dockerfile, docker-compose, and Helm chart
Multi-stage Docker build (node + golang + scratch), ~30MB image.
docker-compose.yml for local development with volume persistence.
Helm chart with configurable Deployment, Service, PVC, Ingress,
and Prometheus ServiceMonitor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Prometheus metrics and Kubernetes health endpoints
Add internal/metrics package with Prometheus collectors (HTTP requests,
duration, messages, agents, connections) and chi-compatible middleware.
Add internal/health package with /healthz (liveness) and /readyz
(readiness with DB ping) endpoints. Wire into main.go with promhttp
handler at /metrics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update Go version to 1.25, fix Docker build issues
- Update Dockerfile golang image from 1.23 to 1.25 (matches go.mod)
- Add tzdata package for timezone support in scratch image
- Use npm install --legacy-peer-deps for web frontend build
- Update CI/release workflows to use Go 1.25
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve CI failures - golangci-lint v2 and npm peer deps
- Upgrade golangci-lint-action to v7 with v2.1 (supports Go 1.25)
- Use npm install --legacy-peer-deps instead of npm ci for web builds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace golangci-lint with go vet (golangci-lint doesn't support Go 1.25 yet)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add internal/metrics package with Prometheus collectors (HTTP requests,
duration, messages, agents, connections) and chi-compatible middleware.
Add internal/health package with /healthz (liveness) and /readyz
(readiness with DB ping) endpoints. Wire into main.go with promhttp
handler at /metrics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major feature additions across backend and frontend:
Backend:
- Unix domain socket admin server with JSON-RPC protocol
- CLI subcommands: user/agent management, audit, backup, messages, channels
- Managed API keys (sb_ prefix) with permissions, channel limits, expiry
- Thread/reply support in messaging core (reply_to column)
- Context-based trace owner_id propagation for proper audit filtering
- Two-step auth middleware supporting both agent keys and managed API keys
Frontend:
- Complete Slack-like dark theme redesign with custom CSS properties
- Sidebar with Channels, Direct Messages, and Admin sections
- Thread panel (slide-in) for viewing message replies
- API key management page with create form, key display, and
ready-to-use MCP/Claude Code config snippets with copy-to-clipboard
- All pages restyled: login, dashboard, agents, conversations, settings
E2E Tests:
- Fixed test runner binary path resolution
- Added pyproject.toml for test dependencies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace deprecated SSE transport with Streamable HTTP (MCP spec
2025-03-26). Add OptionalAuthMiddleware for agent Bearer token
auth on /mcp endpoint — authenticates when token present, passes
through for unauthenticated tools like register_agent.
Also fix .gitignore to only ignore root synapbus binary, not
cmd/synapbus source directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add complete Web UI infrastructure:
Go backend:
- REST API handlers for messages, agents, channels (internal/api/)
- SSE hub for real-time event streaming
- Session-to-owner middleware bridging auth sessions to API context
- SPA file server with go:embed for static assets
- GetMessageByID on MessagingService, RevokeKey on AgentService
- Updated router with RouterConfig for full service wiring
Svelte 5 SPA (web/):
- SvelteKit with static adapter for SPA mode
- Tailwind CSS with dark mode (class-based, localStorage persisted)
- API client with auto-redirect on 401
- SSE client with exponential backoff reconnect
- Pages: Login, Dashboard, Conversations, Channels, Agents, Settings
- Components: Sidebar, Header, MessageList, ComposeForm, AgentCard, TraceViewer
- Responsive layout with mobile sidebar toggle
Build:
- Placeholder index.html in internal/web/dist/ for go:embed compilation
- Updated Makefile web target to copy build output
- All existing Go tests pass, CGO_ENABLED=0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add HNSW-based vector search with configurable embedding providers
(OpenAI, Ollama) and automatic FTS5 fallback when no provider is
configured. Background pipeline embeds messages asynchronously on
ingest, stores vectors in a pure-Go HNSW index, and retries on
failure with exponential backoff. The search_messages MCP tool now
supports search_mode (auto/semantic/fulltext) and returns ranked
results with similarity scores. All existing tests continue to pass,
CGO_ENABLED=0 cross-compilation verified.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add task auction lifecycle with full permission enforcement:
- TaskStore (SQLite) for tasks and bids CRUD, expiry, channel cancellation
- SwarmService with PostTask, BidOnTask, AcceptBid, CompleteTask
- MCP tools: post_task, bid_task, accept_bid, complete_task, list_tasks
- ExpiryWorker background goroutine for deadline-based task cancellation
- Channel type enforcement (auction ops only on auction channels)
- Agent cannot bid on own task, only poster accepts bids, only assignee completes
- Wired into main.go with graceful shutdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add file attachment support with SHA-256 content-addressable storage,
automatic deduplication, MIME detection, and garbage collection for
orphaned files. Includes MCP tools (upload_attachment, download_attachment,
gc_attachments), REST API endpoints for Web UI, and comprehensive tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add complete auth subsystem with OAuth 2.1 authorization server using
ory/fosite, local user accounts with bcrypt password hashing, session
management, and HTTP handlers for the Web UI.
Components:
- User store with bcrypt hashing (configurable cost, default 12), CRUD,
validation (username 3-64 chars alphanumeric+underscore, password 8-72 bytes)
- Session store with secure random IDs, configurable lifetime (default 24h),
expiration cleanup, and per-user invalidation
- OAuth client store with client_id/secret generation and bcrypt verification
- Fosite storage adapter implementing CoreStorage, TokenRevocationStorage,
and PKCERequestStorage backed by SQLite
- OAuth provider configured with authorization code (PKCE S256 mandatory),
client credentials, refresh token rotation, and token introspection
- HTTP handlers: POST /auth/register, POST /auth/login, POST /auth/logout,
GET /auth/me, PUT /auth/password, GET /oauth/authorize, POST /oauth/token,
POST /oauth/introspect
- Middleware: RequireSession (cookie), RequireBearer (access token),
RequireAuth (either), RequireAdmin (role check)
- Structured auth event logging (login, token issuance, session lifecycle)
- Schema migration 002_auth.sql extending users, oauth_clients, oauth_tokens
tables and adding sessions, oauth_authorization_codes tables
- Initial admin user auto-created on first run with random password printed
to stdout
- All tests pass with CGO_ENABLED=0, zero external runtime dependencies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive trace logging and observability features:
- Enhanced trace store with owner-scoped queries, filtering (agent, action,
time range), pagination, streaming export, and retention cleanup
- REST API endpoints: GET /api/traces (list with filters), GET /api/traces/export
(streaming JSON/CSV), GET /api/traces/stats (action counts)
- Owner isolation enforced at every layer (store, API, tests)
- Hand-rolled Prometheus metrics (pure Go, zero CGO): traces_total,
traces_by_action, errors_total, active_agents at GET /metrics
- Configurable slog JSON handler with --log-level flag
- Request ID middleware for cross-referencing logs and traces
- Batch trace writing (64 entries or 100ms flush interval)
- Background retention cleanup via --trace-retention flag
- SQL migration 002 adds owner_id column and composite indexes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the foundational layer that all SynapBus features depend on:
- internal/storage: SQLite connection manager (WAL mode, busy_timeout,
foreign_keys) and embedded migration runner using modernc.org/sqlite
- internal/messaging: MessagingService with send, read inbox, claim,
mark done/failed, and FTS5 search. SQLite-backed MessageStore with
conversation auto-creation and read/unread tracking via inbox_state.
- internal/agents: AgentService with register, authenticate (bcrypt),
update, deregister, discover by capability. HTTP auth middleware.
- internal/mcp: MCP server using mark3labs/mcp-go with 9 registered
tools (send_message, read_inbox, claim_messages, mark_done,
search_messages, register_agent, discover_agents, update_agent,
deregister_agent). SSE transport, health endpoint, connection manager.
- internal/trace: Async trace recorder with buffered channel for
recording agent actions to SQLite traces table.
- cmd/synapbus: Updated main.go wiring storage, migrations, services,
MCP server, chi router, and graceful shutdown.
All code compiles with CGO_ENABLED=0. Full test suite passes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>