Skip to main content

Auth Service

The Auth service is a thin Go wrapper around Clerk, translating Clerk user events into GospeLib domain events and providing a stable internal interface. It manages user records in PostgreSQL and publishes lifecycle events to Redis Streams.

Quick Reference

PropertyValue
Port8200
LanguageGo
FrameworkChi v5
Module pathgithub.com/gospelib/main/services/auth
Entry pointcmd/server/main.go
Auth providerClerk (Phase 1–2), migratable to custom (Phase 3)
Data storePostgreSQL (gl_users table)

Responsibilities

  • Webhook receiver — Handles Clerk user events (user.created, user.updated, session.created)
  • User sync — Persists Clerk user records to the gl_users PostgreSQL table
  • JWT middleware — Shared JWT validation logic reused by the gateway
  • User profiles — Exposes /users/{id} for other services to fetch user data
  • Entitlement join — Exposes /users/{id}/entitlements joining user records with billing plans
  • Event publishing — Publishes user.created / user.updated events to gl:events:users Redis Stream

Why Clerk?

Building a production-grade auth system (MFA, magic links, social auth, session management, device trust) is a 2–6 month project. Clerk handles all of this for $0–$100/month at GospeLib's scale. The auth service exists as a wrapper — swapping Clerk for a custom implementation later changes the wrapper, not anything downstream.

Running Locally

cd services/auth
go run ./cmd/server

The service starts on port 8200 and requires PostgreSQL to be running.

Environment Variables

VariableDefaultDescription
GOSPELIB_AUTH_PORT8200HTTP listen port
GOSPELIB_AUTH_DATABASE_URLpostgres://localhost:5432/gospelibPostgreSQL connection string
GOSPELIB_AUTH_CLERK_WEBHOOK_SECRETClerk webhook signing secret
GOSPELIB_AUTH_CLERK_JWKS_URLClerk JWKS endpoint for JWT validation
GOSPELIB_AUTH_REDIS_URLredis://localhost:6380Redis for event publishing

Health Check

curl http://localhost:8200/health
# {"status": "ok"}

Entry Point Pattern

The cmd/server/main.go follows the standard Go service pattern:

  1. Configure Zerolog (JSON structured logging)
  2. Load config from environment variables
  3. Initialize PostgreSQL connection + run migrations
  4. Create Chi router with middleware
  5. Register routes — health, webhook (public), user endpoints (internal)
  6. Start HTTP server in a goroutine
  7. Wait for SIGINT/SIGTERM
  8. Graceful shutdown with 10-second context

PostgreSQL Schema

CREATE TABLE gl_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
clerk_id TEXT UNIQUE NOT NULL,
email TEXT NOT NULL,
display_name TEXT,
plan_id TEXT NOT NULL DEFAULT 'free',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE gl_user_devices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES gl_users(id) ON DELETE CASCADE,
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android', 'web')),
push_token TEXT,
app_version TEXT,
last_seen_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);

Docker

FROM golang:1.25-alpine AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server

FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app /app
EXPOSE 8200
ENTRYPOINT ["/app"]