KWS is a B2B cloud platform for managing multiple KOS (Kitchen Operating System) instances across different tenants, regions, and sites. It provides centralized recipe management, order routing, and fleet management for autonomous kitchen operations.
-
Go 1.25+
-
Docker and Docker Compose v2
-
MongoDB 8.0+ (runs in Docker)
-
Keycloak 26+ (runs in Docker)
cd ~/src/ak/kws
# Copy production config for local development
cp config/config.prod.yaml config/config.yaml
# Edit config.yaml for local development (optional)
# - Change port if needed
# - Enable debug mode# Start MongoDB and Keycloak containers
docker compose up -d mongodb postgres keycloak
# Wait for services to be ready (about 30 seconds)
docker compose logs -f keycloak # Wait until you see "Keycloak ... started"
# Press Ctrl+C to exit logs# Check MongoDB is running
docker compose exec mongodb mongosh --eval "db.runCommand({ping:1})"
# Check Keycloak is running
curl -s http://localhost:8180/health/ready
# Access Keycloak Admin Console
# URL: http://localhost:8180
# Username: admin
# Password: admin (or $KEYCLOAK_ADMIN_PASSWORD)# Build the application
make build
# Run the server (uses config/config.yaml)
make run
# Or run directly
./bin/kws serve-
Web UI: http://localhost:7000 (or port configured in config.yaml)
| File | Purpose | Git Status |
|---|---|---|
|
Production defaults, committed to git |
Tracked |
|
Local development, secrets allowed |
Gitignored |
|
Additional local overrides |
Gitignored |
All config values can be overridden via environment variables with KWS_ prefix:
export KWS_SERVER_PORT=8080
export KWS_MONGODB_URI=mongodb://production-host:27017
export KWS_KEYCLOAK_URL=https://auth.example.com# config/config.yaml
app:
env: development # development, staging, production
debug: true # Enable debug logging
server:
port: 7000 # HTTP server port
mongodb:
uri: mongodb://localhost:27017
database: kws
keycloak:
url: http://localhost:8180
admin_username: admin
admin_password: admin # Use env var in production!| Service | Port | Description |
|---|---|---|
|
8000:8080 |
KWS Application (only when running full stack) |
|
27017:27017 |
MongoDB for application data |
|
5432 (internal) |
PostgreSQL for Keycloak |
|
8180:8080 |
IAM (Authentication & Authorization) |
|
443, 8443 |
Reverse proxy (production profile only) |
# Start only dependencies (for local development)
docker compose up -d mongodb postgres keycloak
# Start everything including KWS container
docker compose up -d
# View logs
docker compose logs -f kws
docker compose logs -f keycloak
# Stop all services
docker compose down
# Stop and remove volumes (full reset)
docker compose down -v
# Rebuild KWS container after code changes
docker compose build kws
docker compose up -d kws# 1. Start dependencies
docker compose up -d mongodb postgres keycloak
# 2. Build and run locally (faster iteration)
make run
# 3. Make changes, rebuild
make run# Health check
curl http://localhost:7000/health
# List tenants (requires auth in production)
curl http://localhost:7000/api/v1/tenants
# Create a tenant
curl -X POST http://localhost:7000/api/v1/tenants \
-H "Content-Type: application/json" \
-d '{"code": "test-tenant", "name": "Test Tenant", "plan": "starter"}'kws/
├── cmd/kws/ # Application entry point
├── config/ # Configuration files
│ ├── config.prod.yaml # Production defaults (committed)
│ └── config.yaml # Local development (gitignored)
├── docker-compose.yaml # Docker services
├── Dockerfile # Container build
├── docs/ # Documentation (AsciiDoc)
│ ├── KWS-Requirements-Document.adoc
│ ├── KWS-Functional-Specification.adoc
│ └── KWS-Technical-Design.adoc
├── internal/
│ ├── app/ # HTTP handlers, middleware
│ ├── domain/ # Models, repositories, services
│ ├── infrastructure/ # Config, database, external services
│ └── pkg/ # Shared utilities
├── scripts/
│ ├── ca/ # Certificate Authority scripts
│ └── db/ # Database initialization
└── web/ # Web UI (templates, static files)KWS manages KOS instances via REST API with mTLS authentication.
-
KOS instance is provisioned with mTLS client certificate
-
On first startup, KOS generates a UUID and stores it in local database
-
KOS connects to KWS with:
-
mTLS client certificate (transport layer)
-
X-KOS-IDheader with UUID
-
| Endpoint | Method | Description |
|---|---|---|
|
POST |
Register new KOS instance |
|
POST |
Health check (every 60s) |
|
GET |
Get recipes assigned to this KOS |
|
GET |
Get ingredients for assigned recipes |
|
GET |
Get pending orders for this site |
|
POST |
Update order status |
|
POST |
Report locally-created order |
# Check if MongoDB container is running
docker compose ps mongodb
# Check MongoDB logs
docker compose logs mongodb
# Test connection
docker compose exec mongodb mongosh --eval "db.runCommand({ping:1})"# Keycloak takes ~30s to start fully
docker compose logs -f keycloak
# Check health endpoint
curl http://localhost:8180/health/ready
# Reset Keycloak (loses all data)
docker compose down keycloak postgres
docker volume rm kws_postgres-data
docker compose up -d postgres keycloakIf you see template errors like "invalid value; expected int":
-
Check the handler is passing correct data types
-
Ensure pagination fields (Page, TotalPages) are integers
-
Use
{{with .Field}}to handle nil values
| Target | Description |
|---|---|
|
Format and build (default) |
|
Build the binary |
|
Build and run server |
|
Format Go code |
|
Run tests |
|
Run go mod tidy |
|
Remove build artifacts |
|
Start Docker Compose services |
|
Stop Docker Compose services |
-
Requirements Document - System requirements and SOPs
-
Functional Specification - User features and workflows
-
Technical Design - Architecture and schemas
-
CLAUDE.md - AI assistant context and coding guidelines