* docs: expand public user and contributor guides * docs: address public guide review feedback * docs: align web e2e coverage guidance * test: cover collapsed docs references * fix: validate shortcut docs references * fix: parse balanced docs links * fix: handle indented docs code blocks
4.4 KiB
title, description
| title | description |
|---|---|
| Backend Development | Work in Kandev's Go backend using its handler, service, repository, event, and runtime patterns. |
Backend Development
The backend is a Go module rooted at apps/backend. It builds the unified kandev binary and the agentctl helper used inside local, container, and remote task environments.
Run and test the backend
From the repository root:
make dev-backend
make test-backend
make lint-backend
For a package-sized loop:
cd apps/backend
go test -tags fts5 ./internal/task/...
go test -tags fts5 ./internal/mcp/server -run TestName
The fts5 build tag and CGO settings used by the Makefile matter for SQLite search behavior. Reproduce CI through the root targets before concluding that a direct go test result is sufficient.
Follow domain boundaries
A normal backend feature flows through:
- domain model or request DTO;
- repository interface and implementation when persistence changes;
- service method that enforces behavior;
- HTTP or WebSocket handler;
- event publication and gateway notification when clients need real-time state;
- startup wiring in
internal/backendapp/; - unit/integration tests at each changed boundary.
Use the nearest domain's naming and error conventions. Avoid reaching directly into another domain's SQLite repository when a service or interface exists.
HTTP and WebSocket APIs
HTTP routes generally live with a domain's handlers/controllers under /api/v1. Real-time task and agent behavior also uses typed actions from apps/backend/pkg/websocket and gateway broadcasters under internal/gateway/websocket.
When adding or changing a wire field:
- update the Go DTO and web TypeScript type/client together;
- preserve JSON compatibility unless the change is intentionally breaking;
- test malformed input and authorization/workspace scope;
- publish an event only after persistence succeeds;
- consider a reconnecting client that missed the event.
The public WebSocket protocol reference is generated from maintained behavior in WebSocket API.
Persistence and migrations
Domain repositories under internal/*/repository and internal/db own storage. SQLite is the primary local path; PostgreSQL compatibility uses dialect helpers and CI coverage.
- Make migrations forward-safe and deterministic.
- Add repository tests for both new writes and old-row reads.
- Keep transaction scope small.
- Never log secret values.
- Consider startup recovery for statuses that represent in-flight work.
Agent runtime boundary
The backend does not run every agent command directly. internal/agent/runtime/lifecycle coordinates execution, while agentctl owns the process in the task environment. Control DTOs and streams cross that boundary.
Changes to agent launch, MCP injection, terminals, Git operations, or remote behavior often require tests on both sides. Check local, worktree, Docker, and at least one remote-shaped path rather than assuming local process behavior generalizes.
Events and background work
Schedulers, integration watches, automations, workflow reactions, and run queues can execute after the initiating request returns. Make handlers return durable IDs/status, use cancellation-aware contexts, and define deduplication or idempotency where external events can repeat.
Background failures must be observable in persisted status or logs. A goroutine that only logs an error is usually insufficient for user-facing work.
Configuration and secrets
internal/common/config loads server configuration. User-managed credentials go through the secrets domain or provider-specific secret adapter rather than plaintext config rows or logs.
Validate URLs, filesystem paths, shell input, and provider payloads at the boundary. Pay particular attention to prepare scripts, Git refs, archive extraction, MCP destinations, and remote command construction.
Review checklist
- Domain rule lives in a service, not only a handler.
- Repository behavior and migration are tested.
- Events follow durable writes.
- Cancellation, timeout, retry, and duplicate-event behavior are explicit.
- No secrets or agent content leak into logs unexpectedly.
- Web types and public docs match the API.
- Relevant focused tests plus
make test-backendandmake lint-backendpass.
Related: Architecture, Testing, and Extending Kandev.