Head of Product & Engineering a40a4aa626
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: initial implementation of Cast GHL Provider
Complete MVP implementation of the Cast GHL Conversation Provider bridge:
- Go module setup with chi router and mongo-driver dependencies
- Config loading with env var validation and defaults
- MongoDB token store with upsert, get, update, delete operations
- Cast.ph SMS client with 429 retry logic and typed errors
- Phone number normalization (E.164 ↔ Philippine local format)
- GHL OAuth 2.0 install/callback/refresh flow
- GHL webhook handler with ECDSA signature verification (async dispatch)
- GHL API client for message status updates and inbound message stubs
- Multi-stage Dockerfile, docker-compose with MongoDB, Woodpecker CI pipeline
- Unit tests for phone normalization, Cast client, GHL webhook, and OAuth handlers

Co-Authored-By: SideKx <sidekx.ai@sds.dev>
2026-04-04 17:27:05 +02:00

2.6 KiB

Task 01: Project Initialization

Objective

Set up the Go project, directory structure, go.mod, and placeholder files.

Steps

1. Initialize Go module

go mod init github.com/nicknacnic/cast-ghl-provider

(Adjust module path to match your Gitea repo at git.sds.dev)

2. Install dependencies

go get github.com/go-chi/chi/v5
go get go.mongodb.org/mongo-driver/v2/mongo

3. Create directory structure

cmd/server/main.go           # placeholder: log.Println("cast-ghl-provider starting...")
internal/config/config.go    # placeholder: package config
internal/ghl/oauth.go        # placeholder: package ghl
internal/ghl/webhook.go      # placeholder
internal/ghl/api.go          # placeholder
internal/ghl/types.go        # placeholder
internal/cast/client.go      # placeholder: package cast
internal/cast/types.go       # placeholder
internal/phone/normalize.go  # placeholder: package phone
internal/store/mongo.go      # placeholder: package store

4. Create .env.example

PORT=3002
BASE_URL=https://ghl.cast.ph

# GHL OAuth
GHL_CLIENT_ID=
GHL_CLIENT_SECRET=
GHL_WEBHOOK_PUBLIC_KEY=
GHL_CONVERSATION_PROVIDER_ID=

# Cast.ph
CAST_API_KEY=
CAST_API_URL=https://api.cast.ph
CAST_SENDER_ID=

# MongoDB
MONGO_URI=mongodb://localhost:27017/cast-ghl

# Inbound (Phase 2)
INBOUND_API_KEY=

5. Create .gitignore

.env
cast-ghl-provider
/tmp/

6. Create Dockerfile (placeholder)

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

FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /cast-ghl-provider /cast-ghl-provider
EXPOSE 3002
CMD ["/cast-ghl-provider"]

7. Create docker-compose.yaml

services:
  bridge:
    build: .
    ports:
      - "${PORT:-3002}:${PORT:-3002}"
    env_file: .env
    depends_on:
      - mongo
    restart: unless-stopped

  mongo:
    image: mongo:7
    volumes:
      - mongo-data:/data/db
    restart: unless-stopped

volumes:
  mongo-data:

8. Copy API reference docs

  • Copy CAST_API_REFERENCE.md into repo root (from the Cast API docs provided)
  • Create GHL_API_REFERENCE.md with the GHL Conversation Provider docs

9. Verify

go build ./cmd/server/
go vet ./...

Acceptance Criteria

  • go build ./cmd/server/ succeeds
  • go vet ./... passes with no issues
  • All packages have at least a placeholder file
  • .env.example has all config vars documented
  • Dockerfile builds successfully
  • docker-compose.yaml is valid
  • .gitignore excludes .env and binary