Skip to main content

Development Guide

What is the Development Guide?

This guide provides detailed instructions for setting up a local CVT development environment, building and testing the server and SDKs, and working with the codebase.

For contribution guidelines (code style, PR process, code review), see CONTRIBUTING.md.

Prerequisites

Install the following tools before developing CVT:

ToolVersionInstallation
Go1.25+golang.org/dl
Node.js20+nodejs.org
Python3.11+python.org
uvlatestcurl -LsSf https://astral.sh/uv/install.sh | sh
Java21 (Temurin)adoptium.net
Dockerlatestdocker.com
protoc3.x+grpc.io/docs/protoc-installation

Optional but recommended:

# Install grpc-health-probe for health checks
make install-health-probe

Repository Setup

# Clone the repository
git clone https://github.com/sahina/cvt.git
cd cvt

# Build all components (server + Node.js + Python SDKs)
make build

# Verify the setup works
make test

Server Development

The gRPC server is located in the server/ directory.

Architecture Documentation

For detailed information about component design, validation engine, storage layer, and data flow, see the Architecture Documentation.

Directory Structure

server/
├── cvtservice/ # Core service implementation
│ ├── validator_service.go # Main service logic (RPC handlers)
│ ├── cache.go # Ristretto-based schema caching
│ ├── compatibility_engine.go # Breaking change detection
│ ├── interceptors.go # gRPC interceptors for logging, metrics, auth
│ ├── metrics.go # Prometheus metrics collection
│ ├── audit_logger.go # Audit logging for compliance
│ └── schema_metadata.go # Schema metadata management
├── storage/ # Consumer registry persistence
│ ├── storage.go # Storage interface + ConsumerRecord
│ ├── memory.go # In-memory implementation
│ ├── sqlite/ # SQLite implementation + migrations
│ └── postgres/ # PostgreSQL implementation + migrations
├── pb/ # Generated protobuf code
└── testdata/ # Test fixtures

Building the Server

# Build the server binary
make build

# Or build directly with Go
go build -o cvt ./cmd/cvt

Running Locally

# Run server on port 9550 (default)
make run-server

# Or with custom port
CVT_PORT=50053 make run-server

# Run directly
go run ./cmd/cvt serve

Running Tests

# Run server unit tests
make test-server

# Run with coverage report (opens HTML)
make test-coverage

# Run a specific test
go test -v -run TestValidateInteraction ./server/...

# Run with race detection
go test -v -race ./server/...

Docker Development

# Start server + observability stack
make up

# View logs
make logs

# Check health
make health

# Stop everything
make down

Storage Configuration

CVT supports three storage backends. Configure with environment variables:

In-Memory (Default)

# No configuration needed - used by default
make run-server

SQLite

CVT_STORAGE_ENABLED=true \
CVT_STORAGE_TYPE=sqlite \
CVT_STORAGE_DSN=./cvt.db \
make run-server

PostgreSQL

CVT_STORAGE_ENABLED=true \
CVT_STORAGE_TYPE=postgres \
CVT_POSTGRES_HOST=localhost \
CVT_POSTGRES_PORT=5432 \
CVT_POSTGRES_USER=cvt \
CVT_POSTGRES_PASSWORD=secret \
CVT_POSTGRES_DB=cvt \
make run-server

See Configuration Reference for all environment variables.

SDK Development

Node.js SDK

Location: sdks/node/

cd sdks/node

# Install dependencies
npm install

# Build TypeScript
npm run build

# Run tests
npm test

# Run linting
npm run lint

# Run example
npm run example

Python SDK

Location: sdks/python/

cd sdks/python

# Install dependencies (creates virtual environment)
uv sync

# Run tests with coverage
uv run pytest --cov

# Run linting
uv run ruff check .

# Run example
uv run python examples/basic_usage.py

Go SDK

Location: sdks/go/

cd sdks/go

# Download dependencies
go mod download

# Run tests
go test -v ./...

# Run tests with coverage
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Java SDK

Location: sdks/java/

cd sdks/java

# Build the SDK
mvn package

# Run tests
mvn test

# Generate coverage report
mvn test jacoco:report

Protobuf Code Generation

Regenerate protobuf code after modifying api/protos/cvt.proto:

# Generate Go server code (server/pb/)
make generate

# Generate Go SDK code (sdks/go/cvt/proto/)
make generate-go-sdk

# Generate Python SDK code (sdks/python/cvt_sdk/proto/)
make generate-python

# Generate Java SDK code (sdks/java/target/generated-sources/)
make generate-java-sdk

The Node.js SDK uses dynamic proto loading and doesn't require code generation.

TLS/mTLS Development Setup

Generate Certificates

# Generate certificates in ./certs directory
./tools/gen-certs.sh

This creates:

  • ca.crt, ca.key - Certificate Authority
  • server.crt, server.key - Server certificate
  • client.crt, client.key - Client certificate (for mTLS)

Run Server with TLS

CVT_TLS_ENABLED=true \
CVT_TLS_CERT_FILE=./certs/server.crt \
CVT_TLS_KEY_FILE=./certs/server.key \
make run-server

Run Server with mTLS

CVT_TLS_ENABLED=true \
CVT_TLS_CERT_FILE=./certs/server.crt \
CVT_TLS_KEY_FILE=./certs/server.key \
CVT_TLS_CA_FILE=./certs/ca.crt \
CVT_TLS_CLIENT_AUTH=require \
make run-server

Testing SDKs Locally

Test SDK changes in consumer projects without publishing to a registry.

# In the SDK directory
cd sdks/node
npm run build
npm link

# In your consumer project
npm link @sahina/cvt-sdk

Python - Editable Install

# Using uv
uv pip install -e /path/to/cvt/sdks/python

# Using pip
pip install -e /path/to/cvt/sdks/python

Go - replace Directive

Add to your project's go.mod:

replace github.com/sahina/cvt/sdks/go => /path/to/cvt/sdks/go

Java - Install to Local Maven Repository

cd sdks/java
mvn install

Common Development Tasks

Running CI Checks Locally

# Run lint + format checks (no tests)
make ci

# Run lint + format + coverage checks (full CI)
make ci-full

Updating Dependencies

# Update all SDKs
make update

# Update individual components
make update-server
cd sdks/node && npm update
cd sdks/python && uv lock --upgrade
cd sdks/go && go get -u ./...
cd sdks/java && mvn versions:display-dependency-updates

Cleaning Build Artifacts

make clean

Troubleshooting

Server won't start on port 9550

The port may be in use. Specify a different one:

CVT_PORT=50053 make run-server

Tests fail with "connection refused"

Ensure the CVT server is running:

make up
make health

Protobuf generation fails

Ensure protoc and plugins are installed:

which protoc
which protoc-gen-go
which protoc-gen-go-grpc