| name | synapse-dev |
| description | Spin up the Synapse local dev stack (postgres + Go backend), reset the database, run smoke tests against the API. Use when the user asks to "run synapse", "start the backend", "reset the db", "rebuild and run", or wants to manually exercise endpoints. |
Synapse dev workflow
Synapse is the Go control-plane backend in this repo. Its local dev stack is:
- Postgres in Docker (
docker-compose.yml service postgres, port 5432)
- Go backend running on the host on port 8080 (loads
../.env)
Start the stack
docker compose up -d postgres
cd synapse
go run ./cmd/server
If go run errors with SYNAPSE_JWT_SECRET must be set, ensure .env exists
in the repo root: cp .env.example .env.
Build & vet (use before every commit)
cd synapse
go build ./... && go vet ./...
Reset the database (keep schema, drop data)
PGPASSWORD=synapse psql -h localhost -U synapse -d synapse -c \
"TRUNCATE users, teams, projects, team_members, deployments, project_env_vars, \
team_invites, deploy_keys, access_tokens, audit_events, provisioning_jobs, \
deployment_replicas, deployment_storage \
RESTART IDENTITY CASCADE;"
docker rm -f $(docker ps -aq --filter label=synapse.managed=true) 2>/dev/null
docker volume ls -q --filter name=synapse-data- | xargs -r docker volume rm
Plain DELETE FROM users will fail because teams.creator_user_id has
ON DELETE RESTRICT. Either delete teams first or TRUNCATE … RESTART IDENTITY.
If you're between Playwright runs and the worker has in-flight goroutines
from prior jobs, also docker compose restart synapse to nuke them.
HA mode (v0.5+, optional)
By default docker compose up -d runs in single-replica mode. To
exercise the HA path, opt into the ha compose profile and configure
the cluster envs:
docker compose --profile ha up -d
openssl rand -hex 32
docker compose up -d synapse
See docs/HA_TESTING.md for the full operator walkthrough including
pre-creating MinIO buckets. The profile is idle by default — plain
docker compose up -d doesn't bring up the HA services.
Smoke test the API
After running the server, the canonical e2e flow is:
A=$(curl -sf -X POST http://localhost:8080/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"dev@local","password":"strongpass123","name":"Dev"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")
curl -sf -X POST http://localhost:8080/v1/teams/create_team \
-H "Authorization: Bearer $A" \
-H 'Content-Type: application/json' \
-d '{"name":"Test Team"}'
The token is a JWT — paste into Authorization: Bearer <token> for any
authenticated endpoint.
Common pitfalls
- Working directory matters for the
.env loader. The server tries .env,
../.env, ../../.env in that order. Run from synapse/ and the repo-root
.env will be picked up via ../.env.
docker compose ps shows only services in the current name: (project
name in compose v2 → synapse). If postgres is missing, you're in the wrong
directory or the project name was overridden.
- JWT signing uses
SYNAPSE_JWT_SECRET. Changing it invalidates every
outstanding session.
Multi-node dev
To verify the v0.3 hygiene work locally, run two synapse processes:
cd synapse && SYNAPSE_HTTP_ADDR=:8080 go run ./cmd/server
cd synapse && SYNAPSE_HTTP_ADDR=:8081 go run ./cmd/server
Both connect to the same postgres + docker daemon. Hammer
/v1/teams/create_team from N curl loops simultaneously: every request
should get 201 with a unique slug; no 500s. Periodic worker logs should
show only ONE node logging "health sweep" per tick — the other observes
"another node holds the sweep lock; skipping" at DEBUG level.
When NOT to use this skill
- Production deploy decisions — see
docs/ARCHITECTURE.md.
- Editing the dashboard (separate skill once we have one).
- Anything inside the provisioner that requires a live Docker daemon —
the smoke flow does not exercise
Provision/Destroy. Use real
Convex backend image tests for that.