Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/api-contract-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/migrations-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
Expand Down
51 changes: 36 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -271,13 +290,15 @@ All protected endpoints require the `Authorization: Bearer <key>` 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

Expand Down Expand Up @@ -353,4 +374,4 @@ Apache 2.0

## Related Documentation

- [API Documentation](http://localhost:8080/swagger/) - Interactive Swagger documentation (when server is running)
- [OpenAPI spec](openapi.yaml) - API contract (used by Schemathesis); serving it from the server is planned (see [todo.md](todo.md)).
3 changes: 2 additions & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 6 additions & 8 deletions docs/core-concepts/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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" \
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
Loading