diff --git a/.env.example b/.env.example index abb4f6e..6cec73f 100644 --- a/.env.example +++ b/.env.example @@ -6,10 +6,13 @@ # The server will fail to start if this is not set API_KEY=your-secret-api-key-here -# Database connection URL (optional) -# Default: postgres://postgres:postgres@localhost:5433/test_db?sslmode=disable (compose exposes 5433 on host) +# Postgres host port for docker-compose (optional). Default: 5432. Override only if 5432 is in use (e.g. POSTGRES_PORT=5433); keep DATABASE_URL in sync. +# POSTGRES_PORT=5432 + +# Database connection URL (optional). Port must match POSTGRES_PORT when you override it. +# Default: postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable # Format: postgres://username:password@host:port/database?sslmode=disable -DATABASE_URL=postgres://postgres:postgres@localhost:5433/test_db?sslmode=disable +DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable # HTTP server port (optional) # Default: 8080 diff --git a/.github/workflows/api-contract-tests.yml b/.github/workflows/api-contract-tests.yml index 9360f67..6f335a1 100644 --- a/.github/workflows/api-contract-tests.yml +++ b/.github/workflows/api-contract-tests.yml @@ -53,7 +53,7 @@ jobs: - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff with: - go-version: '1.25.6' + go-version: '1.25.7' - name: Cache Go modules uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 1598fd9..5e395b7 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff with: - go-version: '1.25.6' + go-version: '1.25.7' - name: Cache Go modules uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 diff --git a/.github/workflows/migrations-validate.yml b/.github/workflows/migrations-validate.yml index 5c26b27..b84cbb3 100644 --- a/.github/workflows/migrations-validate.yml +++ b/.github/workflows/migrations-validate.yml @@ -25,7 +25,7 @@ jobs: - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff with: - go-version: '1.25.6' + go-version: '1.25.7' - name: Install goose run: go install github.com/pressly/goose/v3/cmd/goose@v3.26.0 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7b7d6c1..ac61342 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff with: - go-version: '1.25.6' + go-version: '1.25.7' - name: Cache Go modules uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 @@ -78,7 +78,7 @@ jobs: - name: Set up Go uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff with: - go-version: '1.25.6' + go-version: '1.25.7' - name: Cache Go modules uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 diff --git a/Makefile b/Makefile index 6522dc3..afe8cf7 100644 --- a/Makefile +++ b/Makefile @@ -63,8 +63,8 @@ run: echo "# API Key for authentication (required)" >> .env; \ echo "API_KEY=test-api-key-12345" >> .env; \ echo "" >> .env; \ - echo "# Database connection URL" >> .env; \ - echo "DATABASE_URL=postgres://postgres:postgres@localhost:5433/test_db?sslmode=disable" >> .env; \ + echo "# Database connection URL (optional: set POSTGRES_PORT in .env if 5432 is in use; keep port in sync here)" >> .env; \ + echo "DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable" >> .env; \ echo "" >> .env; \ echo "# Server port (default: 8080)" >> .env; \ echo "PORT=8080" >> .env; \ diff --git a/README.md b/README.md index c8d9675..e023f66 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,16 @@ An open-source Experience Management (XM) database service. Hub is a headless AP - ✅ **Clean Architecture** with repository, service, and handler layers - ✅ **Docker Compose** for local development - ✅ **Database Schema** initialization -- ✅ **Swagger/OpenAPI** documentation +- ✅ **OpenAPI** spec (`openapi.yaml`) and contract tests (Schemathesis) - ✅ **Health Check** endpoints ## Tech Stack -- **Language**: Go 1.25.6 +- **Language**: Go 1.25.7 - **Database**: PostgreSQL 16 - **Driver**: pgx/v5 - **HTTP**: Standard library `net/http` (barebones approach) -- **Documentation**: Swagger/OpenAPI +- **Documentation**: OpenAPI spec in repo, contract tests (Schemathesis) - **License**: Apache 2.0 ## Project Structure @@ -60,16 +60,16 @@ An open-source Experience Management (XM) database service. Hub is a headless AP │ └── database/ # Database utilities and connection pooling ├── migrations/ # SQL migrations (goose) ├── tests/ # Integration tests -└── docs/ # API documentation (Swagger) +└── docs/ # API and product documentation ``` ## Getting Started ### Prerequisites -- Go 1.25.6 or higher -- Docker and Docker Compose -- Make (optional, for convenience) +- **Go 1.25.7 or higher** — must be [installed](https://go.dev/doc/install) and available on your `PATH`. Verify with `go version`. If `go` is not found, see [Adding Go to PATH](#adding-go-to-path) below. +- **Docker** and **Docker Compose** +- **Make** (optional, for convenience) ### Quick Start @@ -132,7 +132,8 @@ go run ./cmd/api/main.go ### Health Check - `GET /health` - Health check endpoint -- `GET /swagger/` - Swagger API documentation + +The OpenAPI 3.1 spec lives in **`openapi.yaml`** at the repo root and is used by Schemathesis for API contract tests (`make schemathesis`). Serving the spec (e.g. `GET /openapi.json` or Swagger UI) is planned; see [todo.md](todo.md) § OpenAPI. ### Feedback Records @@ -220,6 +221,24 @@ make tests # Integration tests (requires database) make test-all # Run all tests ``` +### Troubleshooting (local development) + +- **`go: command not found` or `make` fails with "go not found"** — Go is not on your `PATH`. Install Go from [go.dev/doc/install](https://go.dev/doc/install), then add it to your PATH using the platform steps in [Adding Go to PATH](#adding-go-to-path) below. Restart the terminal (or re-source your profile) after changing PATH. +- **Docker/Postgres port already in use** (e.g. `5432` or `address already in use`) — Set `POSTGRES_PORT` in `.env` to a free port (e.g. `5433`), and set the same port in `DATABASE_URL` (e.g. `postgres://postgres:postgres@localhost:5433/test_db?sslmode=disable`). Then run `make docker-up` again. + +#### Adding Go to PATH + +After installing Go, your shell must be able to find the `go` binary. Restart the terminal (or re-source your profile) after editing PATH. + +**macOS / Linux (bash or zsh)** +Add this line to `~/.bashrc` or `~/.zshrc` (create the file if it doesn’t exist). It adds the Go toolchain (`go`) and the directory where `go install` puts binaries (e.g. `goose`, `river`) used by the Makefile. + +```bash +export PATH="$PATH:/usr/local/go/bin:$HOME/go/bin" +``` + +If you installed Go via the [Go version manager](https://go.dev/doc/manage-install) (e.g. under `$HOME/sdk/go1.21/bin`), use that directory instead of `/usr/local/go/bin`. To check that Go is on your PATH, run `which go` — it should print the path to the `go` binary. + ### Git Hooks The repository includes pre-commit hooks for code quality. To install them: @@ -271,13 +290,15 @@ All protected endpoints require the `Authorization: Bearer ` header with th ## Environment Variables -See [.env.example](.env.example) for all available configuration options: +Copy [.env.example](.env.example) to `.env` and set values as needed. Reference: -- `DATABASE_URL` - PostgreSQL connection string -- `PORT` - HTTP server port (default: 8080) -- `API_KEY` - API key for authentication (required for protected endpoints) -- `ENV` - Environment (development/production) -- `LOG_LEVEL` - Logging level (debug, info, warn, error) +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `API_KEY` | Yes | — | API key for authenticating requests to protected endpoints. Server will not start without it. | +| `DATABASE_URL` | No | `postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable` | PostgreSQL connection string. Format: `postgres://user:password@host:port/database?sslmode=...`. When using Docker Compose, the host port in this URL must match `POSTGRES_PORT`. | +| `POSTGRES_PORT` | No | `5432` | Host port used by Docker Compose for the Postgres container (`host:container` = `POSTGRES_PORT:5432`). Set this (e.g. `5433`) only if 5432 is already in use; set the same port in `DATABASE_URL`. | +| `PORT` | No | `8080` | HTTP server listen port. | +| `LOG_LEVEL` | No | `info` | Log level: `debug`, `info`, `warn`, or `error`. | ## Example Requests @@ -353,4 +374,4 @@ Apache 2.0 ## Related Documentation -- [API Documentation](http://localhost:8080/swagger/) - Interactive Swagger documentation (when server is running) \ No newline at end of file +- [OpenAPI spec](openapi.yaml) - API contract (used by Schemathesis); serving it from the server is planned (see [todo.md](todo.md)). \ No newline at end of file diff --git a/compose.yml b/compose.yml index 807d5cb..7a6cc28 100644 --- a/compose.yml +++ b/compose.yml @@ -7,8 +7,9 @@ services: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: test_db + # HOST_PORT:CONTAINER_PORT — set POSTGRES_PORT in .env to avoid conflicts (e.g. 5433 if main Formbricks uses 5432) ports: - - '5433:5432' + - "${POSTGRES_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql healthcheck: diff --git a/docs/core-concepts/authentication.mdx b/docs/core-concepts/authentication.mdx index 5faa971..3cf631e 100644 --- a/docs/core-concepts/authentication.mdx +++ b/docs/core-concepts/authentication.mdx @@ -5,7 +5,7 @@ description: "Secure your Hub API with Bearer token authentication." ## How It Works -Hub requires Bearer token authentication. All API endpoints require the `Authorization` header with a Bearer token - except health checks and documentation, which remain public. +Hub requires Bearer token authentication. All API endpoints require the `Authorization` header with a Bearer token — except the health check endpoint, which is public. ## Configuring Authentication @@ -36,7 +36,7 @@ make run ### 3. Include Token in Requests -All API requests (except `/health` and `/docs`) require the `Authorization` header: +All API requests except `GET /health` require the `Authorization` header: ```bash curl -H "Authorization: Bearer your-secret-key-here" \ @@ -57,8 +57,8 @@ These endpoints require authentication: **Always public** (no auth required): - `GET /health` - Health check -- `GET /docs` - API documentation -- `GET /openapi.json` - OpenAPI spec + +The OpenAPI spec is maintained in the repo as **`openapi.yaml`** and used for contract tests (Schemathesis). Serving it at runtime (e.g. `GET /openapi.json` or `GET /docs`) is planned; see [todo.md](../../todo.md) § OpenAPI. ## Authentication Workflow @@ -252,11 +252,9 @@ Health checks (`/health`) should **never** require auth. If you see this, it's a bug. Please [report it](https://github.com/formbricks/hub/issues). -### Docs Page Returns 401 - -The `/docs` endpoint should always be public. +### Future spec endpoint -If you see this, it's a bug. Please [report it](https://github.com/formbricks/hub/issues). +If you add a `/docs` or `/openapi.json` endpoint to serve the API spec, it should remain public (no auth). See [todo.md](../../todo.md) § OpenAPI. ## Examples diff --git a/go.mod b/go.mod index 80ee02c..c8c1784 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/formbricks/hub -go 1.25.6 +go 1.25.7 require ( github.com/go-playground/form/v4 v4.3.0 diff --git a/tests/README.md b/tests/README.md index f8f735d..f603f99 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,7 +6,7 @@ This directory contains integration tests for the Formbricks Hub API. Before running the tests, ensure: -1. **PostgreSQL is running** with the default test credentials (e.g. `make docker-up`). The tests use `postgres://postgres:postgres@localhost:5433/test_db` by default (compose exposes Postgres on host port 5433). If you see `password authentication failed for user "postgres"`, start the stack with `make docker-up` and run `make init-db`. +1. **PostgreSQL is running** with the default test credentials (e.g. `make docker-up`). The tests use `DATABASE_URL` from your `.env` (default `localhost:5432`). If you set `POSTGRES_PORT` in `.env` to avoid port conflicts, set the same port in `DATABASE_URL`. If you see `password authentication failed for user "postgres"`, start the stack with `make docker-up` and run `make init-db`. 2. **Database schema** has been initialized (`make init-db`). 3. **API_KEY** is set automatically by the tests; you do not need to set it.