A community based topic aggregation platform built on atproto

chore: add OAuth config and dependencies

- Add OAuth and Universal Links env vars to example
- Update go.mod/go.sum with required dependencies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Changed files
+118 -11
+111 -11
.env.prod.example
···
POSTGRES_USER=coves_user
POSTGRES_PASSWORD=CHANGE_ME_SECURE_PASSWORD_HERE
+
# Full connection string (alternative to individual vars above)
+
# DATABASE_URL=postgres://coves_user:password@localhost:5432/coves_prod?sslmode=require
+
# =============================================================================
# PDS (Personal Data Server)
# =============================================================================
+
# PDS URL for XRPC calls
+
PDS_URL=https://pds.coves.social
+
# Generate with: openssl rand -hex 32
PDS_JWT_SECRET=CHANGE_ME_64_HEX_CHARS
···
# Generate with: openssl rand -hex 32
PDS_ROTATION_KEY=CHANGE_ME_64_HEX_CHARS
+
# Coves instance PDS account (for creating community records)
+
PDS_INSTANCE_HANDLE=coves.social
+
PDS_INSTANCE_PASSWORD=CHANGE_ME_INSTANCE_PASSWORD
+
# Optional: Email configuration for account recovery
# PDS_EMAIL_SMTP_URL=smtp://user:pass@smtp.example.com:587
-
# PDS_EMAIL_FROM_ADDRESS=noreply@coves.me
+
# PDS_EMAIL_FROM_ADDRESS=noreply@coves.social
+
+
# =============================================================================
+
# Identity & Federation
+
# =============================================================================
+
# PLC Directory URL for DID resolution
+
# Defaults to https://plc.directory if not set
+
# PLC_DIRECTORY_URL=https://plc.directory
+
+
# Instance DID (did:web or did:plc)
+
INSTANCE_DID=did:web:coves.social
+
+
# Instance domain (required if not using did:web)
+
# INSTANCE_DOMAIN=coves.social
+
+
# Identity cache TTL (Go duration format)
+
# IDENTITY_CACHE_TTL=5m
# =============================================================================
# JWT Authentication
···
#
# HS256_ISSUERS: Comma-separated list of PDS URLs allowed to use HS256
# These PDSes MUST share the same PDS_JWT_SECRET with Coves
-
# Example: HS256_ISSUERS=https://pds.coves.social,https://pds.example.com
-
HS256_ISSUERS=https://pds.coves.me
-
-
# PLC Directory URL for DID resolution (optional)
-
# Defaults to https://plc.directory if not set
-
# PLC_DIRECTORY_URL=https://plc.directory
+
HS256_ISSUERS=https://pds.coves.social
# Skip JWT signature verification (DEVELOPMENT ONLY!)
# Set to false in production for proper security
AUTH_SKIP_VERIFY=false
# =============================================================================
-
# AppView OAuth (for mobile app authentication)
+
# OAuth Configuration
# =============================================================================
-
OAUTH_CLIENT_ID=https://coves.social/client-metadata.json
+
# AppView public URL (used for OAuth callback and client metadata)
+
APPVIEW_PUBLIC_URL=https://coves.social
+
+
# OAuth client ID (usually your client-metadata.json URL)
+
OAUTH_CLIENT_ID=https://coves.social/oauth/client-metadata.json
+
+
# OAuth callback URI
OAUTH_REDIRECT_URI=https://coves.social/oauth/callback
# Generate EC P-256 private key in JWK format
# See: https://atproto.com/specs/oauth#client-metadata
+
# Generate with: go run cmd/genjwks/main.go
OAUTH_PRIVATE_JWK={"kty":"EC","crv":"P-256","x":"...","y":"...","d":"..."}
+
# Seal secret for encrypting mobile session tokens (AES-256-GCM)
+
# Generate with: openssl rand -base64 32
+
OAUTH_SEAL_SECRET=CHANGE_ME_BASE64_32_BYTES
+
+
# Optional: OAuth client secret and key ID (for confidential clients)
+
# OAUTH_CLIENT_SECRET=
+
# OAUTH_CLIENT_KID=
+
# =============================================================================
-
# AppView Encryption
+
# Mobile Universal Links & App Links
+
# =============================================================================
+
# Required for iOS Universal Links
+
# Format: <Team ID>.<Bundle ID>
+
# Find Team ID: Apple Developer Portal -> Membership
+
# Find Bundle ID: Xcode project -> General -> Bundle Identifier
+
APPLE_APP_ID=ABCD1234EF.social.coves.app
+
+
# Required for Android App Links
+
# Format: Android package name (reverse domain notation)
+
ANDROID_PACKAGE_NAME=social.coves.app
+
+
# SHA-256 fingerprint of your Android app's signing certificate
+
# Get with: keytool -list -v -keystore release.jks -alias release
+
# Format: 64 hex characters with colons (AA:BB:CC:...)
+
ANDROID_SHA256_FINGERPRINT=AA:BB:CC:DD:EE:FF:11:22:33:44:55:66:77:88:99:00:AA:BB:CC:DD:EE:FF:11:22:33:44:55:66:77:88:99:00
+
+
# =============================================================================
+
# Security & Encryption
# =============================================================================
# For encrypting community credentials in database
# Generate with: openssl rand -base64 32
ENCRYPTION_KEY=CHANGE_ME_BASE64_ENCODED_KEY
+
# Secret for HMAC signing of pagination cursors
+
# Generate with: openssl rand -base64 32
+
CURSOR_SECRET=CHANGE_ME_CURSOR_SECRET
+
+
# Optional: Restrict community creation to specific DIDs
+
# Comma-separated list. If not set, any authenticated user can create communities.
+
# COMMUNITY_CREATORS=did:plc:abc123,did:plc:def456
+
+
# =============================================================================
+
# Jetstream Configuration (Real-time Event Indexing)
+
# =============================================================================
+
# User profile indexing
+
JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.actor.profile
+
+
# Optional: Filter Jetstream events to specific PDS
+
# JETSTREAM_PDS_FILTER=pds.coves.social
+
+
# Community event indexing (profiles and subscriptions)
+
# COMMUNITY_JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=social.coves.community.profile&wantedCollections=social.coves.community.subscription
+
+
# Post indexing
+
# POST_JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=social.coves.community.post
+
+
# Vote indexing
+
# VOTE_JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=social.coves.feed.vote
+
+
# Comment indexing
+
# COMMENT_JETSTREAM_URL=wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=social.coves.community.comment
+
+
# Aggregator indexing
+
# AGGREGATOR_JETSTREAM_URL=
+
# =============================================================================
# Cloudflare (for wildcard SSL certificates)
# =============================================================================
# Required for *.coves.social wildcard certificate
-
# Create at: Cloudflare Dashboard → My Profile → API Tokens → Create Token
+
# Create at: Cloudflare Dashboard -> My Profile -> API Tokens -> Create Token
# Template: "Edit zone DNS" with permissions for coves.social zone
CLOUDFLARE_API_TOKEN=CHANGE_ME_CLOUDFLARE_TOKEN
+
+
# =============================================================================
+
# Server Configuration
+
# =============================================================================
+
# HTTP server port
+
PORT=8080
+
+
# Environment
+
ENV=production
+
IS_DEV_ENV=false
+
+
# Skip did:web domain verification (DEVELOPMENT ONLY!)
+
# MUST be false in production to prevent domain spoofing
+
SKIP_DID_WEB_VERIFICATION=false
# =============================================================================
# Optional: Versioning
+2
go.mod
···
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
+
github.com/go-chi/cors v1.2.2 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
+
github.com/google/go-querystring v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
+5
go.sum
···
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
+
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
+
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
···
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
+
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=