4c9a818bd9efbd9e05abeed677fad36c797374ee
Predicates (20 cases): IsRecurring, IsOneTime, IsDueSoon, HasCompletions, GetCompletionCount, IsUpcoming edge cases Task creation (10): NextDueDate initialization, all frequency types, past dates, all optional fields, access validation One-time completion (8): NextDueDate→nil, InProgress reset, notes/cost/rating, double completion, backdated completed_at Recurring completion (16): Daily/Weekly/BiWeekly/Monthly/Quarterly/ Yearly/Custom frequencies, late/early completion timing, multiple sequential completions, no-original-DueDate, CompletedFromColumn capture QuickComplete (5): one-time, recurring, widget notes, 404, 403 State transitions (10): Cancel→Complete, Archive→Complete, InProgress cycles, recurring full lifecycle, Archive→Unarchive column restore Kanban column priority (7): verify chain priority order for all columns Optimistic locking (7): correct/stale version, conflict on complete/ cancel/archive/mark-in-progress, rollback verification Deletion (5): single/multi/middle completion deletion, NextDueDate recalculation, InProgress restore behavior documented Edge cases (9): boundary dates, late/early recurring, nil/zero frequency days, custom intervals, version conflicts Handler validation (4): rating bounds, title/description length, custom interval validation All 679 tests pass.
honeyDue API
Go REST API for the honeyDue property management platform. Powers iOS and Android mobile apps built with Kotlin Multiplatform.
Tech Stack
- Language: Go 1.24
- HTTP Framework: Echo v4
- ORM: GORM with PostgreSQL
- Background Jobs: Asynq (Redis-backed)
- Push Notifications: APNs (apns2) + FCM HTTP API
- Caching: Redis
- Logging: zerolog
- Configuration: Viper
- Admin Panel: Next.js (separate build target)
Prerequisites
- Go 1.24+ — install
- PostgreSQL 16+ — via Docker (recommended) or native install
- Redis 7+ — via Docker (recommended) or native install
- Docker & Docker Compose — install (recommended for local development)
- Make — pre-installed on macOS;
apt install makeon Linux
Getting Started on a New Machine
Option A: Docker (Recommended)
This starts PostgreSQL, Redis, the API server, background worker, and admin panel in containers using the self-contained dev compose file.
# 1. Clone the repo
git clone <repo-url>
cd honeyDueAPI-go
# 2. Create your environment file
cp .env.example .env
# Edit .env — at minimum set SECRET_KEY to a random 32+ char string
# 3. Build and start all services
make docker-dev
# 4. Seed the database with lookup data (required)
docker exec -i honeydue-db psql -U honeydue -d honeydue < seeds/001_lookups.sql
# 5. (Optional) Seed test data — creates test users, residences, tasks
docker exec -i honeydue-db psql -U honeydue -d honeydue < seeds/002_test_data.sql
docker exec -i honeydue-db psql -U honeydue -d honeydue < seeds/003_task_templates.sql
# 6. Verify the API is running
curl http://localhost:8000/api/health/
The API is now available at http://localhost:8000.
Option B: Run Locally (No Docker for the API)
Use Docker for PostgreSQL and Redis, but run the Go server natively for faster iteration.
# 1. Clone and enter the repo
git clone <repo-url>
cd honeyDueAPI-go
# 2. Install Go dependencies
make deps
# 3. Start PostgreSQL and Redis via Docker
docker compose -f docker-compose.dev.yml up -d db redis
# 4. Create your environment file
cp .env.example .env
# Edit .env:
# - Set SECRET_KEY to a random 32+ char string
# - Set DB_HOST=localhost
# - Set DB_PORT=5433 (docker-compose maps 5433 externally)
# - Set REDIS_URL=redis://localhost:6379/0
# 5. Seed the database
psql -h localhost -p 5433 -U honeydue -d honeydue < seeds/001_lookups.sql
psql -h localhost -p 5433 -U honeydue -d honeydue < seeds/002_test_data.sql
psql -h localhost -p 5433 -U honeydue -d honeydue < seeds/003_task_templates.sql
# 6. Run the API server
make run
# 7. (Optional) Run the background worker in a separate terminal
make run-worker
Option C: Fully Native (No Docker)
Install PostgreSQL and Redis natively on your machine.
# macOS with Homebrew
brew install postgresql@16 redis
# Start services
brew services start postgresql@16
brew services start redis
# Create the database
createdb honeydue
# Then follow Option B steps 2-7, using:
# DB_HOST=localhost, DB_PORT=5432, POSTGRES_USER=<your-user>, POSTGRES_PASSWORD=<your-password>
Environment Variables
Copy .env.example to .env and configure:
| Variable | Description | Default | Required |
|---|---|---|---|
PORT |
Server port | 8000 |
No |
DEBUG |
Enable debug logging | true |
No |
SECRET_KEY |
JWT signing secret (32+ chars) | — | Yes |
POSTGRES_DB |
Database name | honeydue |
Yes |
POSTGRES_USER |
Database user | postgres |
Yes |
POSTGRES_PASSWORD |
Database password | — | Yes |
DB_HOST |
Database host | localhost |
Yes |
DB_PORT |
Database port | 5432 |
Yes |
REDIS_URL |
Redis connection URL | redis://localhost:6379/0 |
Yes |
EMAIL_HOST |
SMTP server | smtp.gmail.com |
For email |
EMAIL_HOST_USER |
SMTP username | — | For email |
EMAIL_HOST_PASSWORD |
SMTP app password | — | For email |
APNS_AUTH_KEY_PATH |
Path to APNs .p8 key file |
— | For iOS push |
APNS_AUTH_KEY_ID |
APNs key ID | — | For iOS push |
APNS_TEAM_ID |
Apple Team ID | — | For iOS push |
FCM_SERVER_KEY |
Firebase server key | — | For Android push |
Project Structure
honeyDueAPI-go/
├── cmd/
│ ├── api/main.go # API server entry point
│ └── worker/main.go # Background worker entry point
├── internal/
│ ├── config/ # Viper configuration
│ ├── database/ # PostgreSQL connection setup
│ ├── models/ # GORM models (map to PostgreSQL tables)
│ ├── repositories/ # Data access layer
│ ├── services/ # Business logic
│ ├── handlers/ # HTTP handlers (Echo)
│ ├── middleware/ # Auth, timezone, logging middleware
│ ├── router/ # Route registration
│ ├── dto/ # Request/Response DTOs
│ │ ├── requests/ # Incoming request structs
│ │ └── responses/ # Outgoing response structs
│ ├── task/ # Centralized task logic
│ │ ├── predicates/ # IsCompleted, IsOverdue, etc.
│ │ ├── scopes/ # GORM query scopes
│ │ └── categorization/ # Kanban column assignment
│ ├── apperrors/ # Structured error types
│ ├── push/ # APNs + FCM push notification clients
│ ├── worker/ # Asynq background jobs
│ ├── i18n/ # Internationalization (en, es, fr)
│ ├── validator/ # Input validation
│ ├── monitoring/ # Health checks
│ └── integration/ # Integration + contract tests
├── admin/ # Next.js admin panel
├── migrations/ # SQL migration files
├── seeds/ # Seed data (lookups, test users)
├── templates/emails/ # Email templates
├── docs/ # API docs, OpenAPI spec
├── docker-compose.yml # Production / Docker Swarm config
├── docker-compose.dev.yml # Self-contained local dev config
├── Dockerfile # Multi-stage build (api, worker, admin)
├── Makefile # Build, test, Docker commands
└── .env.example # Environment variable template
Development
Common Commands
make run # Run API server
make run-worker # Run background worker
make deps # Install/tidy Go dependencies
make build # Build API binary
make build-all # Build API + worker binaries
make fmt # Format code
make vet # Vet code
make lint # Run golangci-lint
make clean # Remove build artifacts
Testing
make test # Run all tests with race detection + coverage
make test-coverage # Run tests and generate HTML coverage report
make contract-test # Run route + KMP contract validation tests
# Run specific packages
go test ./internal/handlers -v
go test -run TestTaskHandler_CreateTask ./internal/handlers
Docker
Two compose files:
docker-compose.dev.yml— self-contained local dev (build from source,container_name,depends_on, dev defaults)docker-compose.yml— production / Docker Swarm (image refs,deploy:sections, overlay network)
# Dev
make docker-dev # Build and start all dev containers (foreground)
make docker-up # Start dev containers (detached)
make docker-down # Stop dev containers
make docker-logs # Tail dev container logs
make docker-restart # Restart dev containers
# Prod
make docker-build-prod # Build production images (api, worker, admin)
Database Migrations
make migrate-up # Apply pending migrations
make migrate-down # Roll back last migration
make migrate-create name=add_column # Create a new migration pair
Seed Data
Seed files in seeds/:
| File | Purpose | Required |
|---|---|---|
001_lookups.sql |
Residence types, task categories, priorities, frequencies, contractor specialties | Yes |
002_test_data.sql |
Test users, residences, tasks, contractors, documents, notifications | Dev only |
003_task_templates.sql |
Pre-built task templates for onboarding | Dev only |
003_admin_user.sql |
Admin panel user | If using admin |
Test Users
All test users have password: password123
| Username | Tier | Notes | |
|---|---|---|---|
| admin | admin@example.com | Pro | Admin user |
| john | john@example.com | Pro | Owns 2 residences |
| jane | jane@example.com | Free | Owns 1 residence, shared access |
| bob | bob@example.com | Free | Owns 1 residence |
API Documentation
- OpenAPI spec:
docs/openapi.yaml(81 paths, 104 operations, 81 schemas) - Health check:
GET /api/health/ - Auth:
POST /api/auth/login/,POST /api/auth/register/ - Static data:
GET /api/static_data/(ETag-cached lookups)
All protected endpoints require an Authorization: Token <token> header.
Production Deployment
Dokku
# Push to Dokku
git push dokku main
# Seed lookup data
cat seeds/001_lookups.sql | dokku postgres:connect honeydue-db
# Check logs
dokku logs honeydue-api -t
Docker Swarm
# Build and push production images
make docker-build-prod
docker push ${REGISTRY}/honeydue-api:${TAG}
docker push ${REGISTRY}/honeydue-worker:${TAG}
docker push ${REGISTRY}/honeydue-admin:${TAG}
# Deploy the stack (all env vars must be set in .env or environment)
docker stack deploy -c docker-compose.yml honeydue
Related Projects
- Mobile App (KMM):
../HoneyDueKMM— Kotlin Multiplatform iOS/Android client - Task Logic Docs:
docs/TASK_LOGIC_ARCHITECTURE.md— required reading before task-related work - Push Notification Docs:
docs/PUSH_NOTIFICATIONS.md
License
Proprietary — honeyDue
Description
Languages
Go
75.5%
TypeScript
20.3%
Shell
2.4%
HTML
0.7%
CSS
0.7%
Other
0.2%