From 939e48a3b100f0d6c2f712dc0a21644dfa327a81 Mon Sep 17 00:00:00 2001 From: Bretton Date: Sun, 2 Nov 2025 14:52:45 -0800 Subject: [PATCH] feat(dev): add mobile testing infrastructure and environment fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add mobile testing targets to Makefile (adb port forwarding, ngrok) - Fix PDS port configuration (3000→3001 for correct DID registration) - Add AUTH_SKIP_VERIFY flag for local JWT development - Add scripts for mobile port setup and ngrok tunnels - Add bin/ to .gitignore for build artifacts Enables USB-connected Android testing and iOS/WiFi testing via ngrok 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .env.dev | 6 ++ .gitignore | 3 +- Makefile | 23 ++++++- docker-compose.dev.yml | 15 ++--- scripts/dev-run.sh | 14 ++++ scripts/setup-mobile-ports.sh | 68 ++++++++++++++++++++ scripts/start-ngrok.sh | 116 ++++++++++++++++++++++++++++++++++ scripts/stop-ngrok.sh | 26 ++++++++ 8 files changed, 259 insertions(+), 12 deletions(-) create mode 100755 scripts/dev-run.sh create mode 100755 scripts/setup-mobile-ports.sh create mode 100755 scripts/start-ngrok.sh create mode 100755 scripts/stop-ngrok.sh diff --git a/.env.dev b/.env.dev index 96450ba..9d30350 100644 --- a/.env.dev +++ b/.env.dev @@ -143,6 +143,12 @@ IS_DEV_ENV=true # When false, hostedByDID must match the community handle domain SKIP_DID_WEB_VERIFICATION=true +# Authentication: Skip JWT signature verification for local development (Phase 1) +# IMPORTANT: Set to false in production for full signature verification +# When true, only parses JWT without verifying signature (trusts any valid JWT format) +# When false, verifies JWT signature against issuer's JWKS +AUTH_SKIP_VERIFY=true + # Logging LOG_LEVEL=debug LOG_ENABLED=true diff --git a/.gitignore b/.gitignore index f58800a..5d6f0df 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,5 @@ Thumbs.db *.temp # Build artifacts -/validate-lexicon \ No newline at end of file +/validate-lexicon +/bin/ \ No newline at end of file diff --git a/Makefile b/Makefile index 9e4b036..97fd962 100644 --- a/Makefile +++ b/Makefile @@ -191,9 +191,8 @@ build: ## Build the Coves server @go build -o server ./cmd/server @echo "$(GREEN)✓ Build complete: ./server$(RESET)" -run: ## Run the Coves server (requires database running) - @echo "$(GREEN)Starting Coves server...$(RESET)" - @go run ./cmd/server +run: ## Run the Coves server with dev environment (requires database running) + @./scripts/dev-run.sh ##@ Cleanup @@ -226,6 +225,24 @@ quick-restart: ## Quick restart of development stack (keeps data) @make dev-down @make dev-up +##@ Mobile Testing + +mobile-setup: ## Setup Android port forwarding for USB-connected devices (recommended) + @echo "$(CYAN)Setting up Android mobile testing environment...$(RESET)" + @./scripts/setup-mobile-ports.sh + +mobile-reset: ## Remove all Android port forwarding + @echo "$(YELLOW)Removing Android port forwarding...$(RESET)" + @adb reverse --remove-all || echo "$(YELLOW)No device connected$(RESET)" + @echo "$(GREEN)✓ Port forwarding removed$(RESET)" + +ngrok-up: ## Start ngrok tunnels (for iOS or WiFi testing - requires paid plan for 3 tunnels) + @echo "$(GREEN)Starting ngrok tunnels for mobile testing...$(RESET)" + @./scripts/start-ngrok.sh + +ngrok-down: ## Stop all ngrok tunnels + @./scripts/stop-ngrok.sh + ##@ Utilities validate-lexicon: ## Validate all Lexicon schemas diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 447a80a..299a53b 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -64,11 +64,11 @@ services: image: ghcr.io/bluesky-social/pds:latest container_name: coves-dev-pds ports: - - "3001:3000" # PDS XRPC API (avoiding production PDS on :3000) + - "3001:3001" # PDS XRPC API (avoiding production PDS on :3000) environment: # PDS Configuration PDS_HOSTNAME: ${PDS_HOSTNAME:-localhost} - PDS_PORT: 3000 + PDS_PORT: 3001 # Match external port for correct DID registration PDS_DATA_DIRECTORY: /pds PDS_BLOBSTORE_DISK_LOCATION: /pds/blocks PDS_DID_PLC_URL: ${PDS_DID_PLC_URL:-https://plc.directory} @@ -101,7 +101,7 @@ services: networks: - coves-dev healthcheck: - test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/xrpc/_health"] + test: ["CMD", "wget", "--spider", "-q", "http://localhost:3001/xrpc/_health"] interval: 10s timeout: 5s retries: 5 @@ -128,7 +128,7 @@ services: - "6009:6009" # Metrics endpoint environment: # Point Jetstream at local PDS firehose - JETSTREAM_WS_URL: ws://pds:3000/xrpc/com.atproto.sync.subscribeRepos + JETSTREAM_WS_URL: ws://pds:3001/xrpc/com.atproto.sync.subscribeRepos # Server configuration JETSTREAM_LISTEN_ADDR: ":6008" @@ -154,11 +154,10 @@ services: depends_on: pds: condition: service_healthy + # Health check disabled for dev - container has no HTTP clients installed + # Jetstream logs show it connects and runs successfully healthcheck: - test: ["CMD", "wget", "--spider", "-q", "http://localhost:6009/metrics"] - interval: 10s - timeout: 5s - retries: 5 + disable: true profiles: - jetstream diff --git a/scripts/dev-run.sh b/scripts/dev-run.sh new file mode 100755 index 0000000..2535c17 --- /dev/null +++ b/scripts/dev-run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Development server runner - loads .env.dev before starting + +set -a # automatically export all variables +source .env.dev +set +a + +echo "🚀 Starting Coves server in DEV mode..." +echo " IS_DEV_ENV: $IS_DEV_ENV" +echo " PLC_DIRECTORY_URL: $PLC_DIRECTORY_URL" +echo " JETSTREAM_URL: $JETSTREAM_URL" +echo "" + +go run ./cmd/server diff --git a/scripts/setup-mobile-ports.sh b/scripts/setup-mobile-ports.sh new file mode 100755 index 0000000..7fddab8 --- /dev/null +++ b/scripts/setup-mobile-ports.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Setup adb reverse port forwarding for mobile testing +# This allows the mobile app to access localhost services on the dev machine + +set -e + +# Colors +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +echo -e "${CYAN}📱 Setting up Android port forwarding for Coves mobile testing...${NC}" +echo "" + +# Check if adb is available +if ! command -v adb &> /dev/null; then + echo -e "${RED}✗ adb not found${NC}" + echo "Install Android SDK Platform Tools: https://developer.android.com/studio/releases/platform-tools" + exit 1 +fi + +# Check if device is connected +DEVICES=$(adb devices | grep -v "List" | grep "device$" | wc -l) +if [ "$DEVICES" -eq 0 ]; then + echo -e "${RED}✗ No Android devices connected${NC}" + echo "Connect a device via USB or start an emulator" + exit 1 +fi + +echo -e "${YELLOW}Setting up port forwarding...${NC}" + +# Forward ports from Android device to localhost +adb reverse tcp:3000 tcp:3001 # PDS (internal port in DID document) +adb reverse tcp:3001 tcp:3001 # PDS (external port) +adb reverse tcp:3002 tcp:3002 # PLC Directory +adb reverse tcp:8081 tcp:8081 # AppView + +echo "" +echo -e "${GREEN}✅ Port forwarding configured successfully!${NC}" +echo "" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo -e "${CYAN} PORT FORWARDING ${NC}" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo "" +echo -e "${GREEN}PDS (3000):${NC} localhost:3001 → device:3000 ${YELLOW}(DID document port)${NC}" +echo -e "${GREEN}PDS (3001):${NC} localhost:3001 → device:3001" +echo -e "${GREEN}PLC (3002):${NC} localhost:3002 → device:3002" +echo -e "${GREEN}AppView (8081):${NC} localhost:8081 → device:8081" +echo "" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo "" +echo -e "${CYAN}📱 Next Steps:${NC}" +echo "" +echo -e "1. Mobile app is already configured for localhost (environment_config.dart)" +echo "" +echo -e "2. Run mobile app:" +echo -e " ${YELLOW}cd /home/bretton/Code/coves-mobile${NC}" +echo -e " ${YELLOW}flutter run --dart-define=ENVIRONMENT=local${NC}" +echo "" +echo -e "3. Login with:" +echo -e " Handle: ${CYAN}charlie.local.coves.dev${NC}" +echo -e " Password: ${CYAN}charliepass123${NC}" +echo "" +echo -e "${YELLOW}💡 Note: Port forwarding persists until device disconnects or you run:${NC}" +echo -e "${YELLOW} adb reverse --remove-all${NC}" +echo "" diff --git a/scripts/start-ngrok.sh b/scripts/start-ngrok.sh new file mode 100755 index 0000000..6649e3f --- /dev/null +++ b/scripts/start-ngrok.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# Automated ngrok tunnel starter for mobile testing +# Starts 3 ngrok tunnels and captures their HTTPS URLs + +set -e + +# Colors +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${CYAN}🚀 Starting ngrok tunnels for Coves mobile testing...${NC}" +echo "" + +# Kill any existing ngrok processes +pkill -f "ngrok http" || true +sleep 2 + +# Start ngrok tunnels using separate processes (simpler, works with any config version) +echo -e "${YELLOW}Starting PDS tunnel (port 3001)...${NC}" +ngrok http 3001 --log=stdout > /tmp/ngrok-pds.log 2>&1 & +sleep 1 + +echo -e "${YELLOW}Starting PLC tunnel (port 3002)...${NC}" +ngrok http 3002 --log=stdout > /tmp/ngrok-plc.log 2>&1 & +sleep 1 + +echo -e "${YELLOW}Starting AppView tunnel (port 8081)...${NC}" +ngrok http 8081 --log=stdout > /tmp/ngrok-appview.log 2>&1 & + +# Get all PIDs +PIDS=$(pgrep -f "ngrok http") +NGROK_PID=$PIDS + +# Save PID for cleanup +echo "$NGROK_PID" > /tmp/ngrok-pids.txt + +# Wait for ngrok to initialize +echo "" +echo -e "${YELLOW}Waiting for tunnels to initialize...${NC}" +sleep 7 + +# Fetch URLs from ngrok API (single API at port 4040) +echo "" +echo -e "${GREEN}✅ Tunnels started successfully!${NC}" +echo "" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo -e "${CYAN} NGROK TUNNEL URLS ${NC}" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo "" + +# Get all tunnel info +TUNNELS=$(curl -s http://localhost:4040/api/tunnels 2>/dev/null || echo "") + +# Extract URLs by matching port in config.addr +PDS_URL=$(echo "$TUNNELS" | jq -r '.tunnels[] | select(.config.addr | contains("3001")) | select(.proto=="https") | .public_url' 2>/dev/null | head -1) +PLC_URL=$(echo "$TUNNELS" | jq -r '.tunnels[] | select(.config.addr | contains("3002")) | select(.proto=="https") | .public_url' 2>/dev/null | head -1) +APPVIEW_URL=$(echo "$TUNNELS" | jq -r '.tunnels[] | select(.config.addr | contains("8081")) | select(.proto=="https") | .public_url' 2>/dev/null | head -1) + +# Fallback if jq filtering fails - just get first 3 HTTPS URLs +if [ -z "$PDS_URL" ] || [ -z "$PLC_URL" ] || [ -z "$APPVIEW_URL" ]; then + echo -e "${YELLOW}⚠️ Port-based matching failed, using fallback...${NC}" + URLS=($(echo "$TUNNELS" | jq -r '.tunnels[] | select(.proto=="https") | .public_url' 2>/dev/null)) + PDS_URL=${URLS[0]:-ERROR} + PLC_URL=${URLS[1]:-ERROR} + APPVIEW_URL=${URLS[2]:-ERROR} +fi + +echo -e "${GREEN}PDS (3001):${NC} $PDS_URL" +echo -e "${GREEN}PLC (3002):${NC} $PLC_URL" +echo -e "${GREEN}AppView (8081):${NC} $APPVIEW_URL" + +echo "" +echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}" +echo "" + +# Check if any URLs failed +if [[ "$PDS_URL" == "ERROR" ]] || [[ "$PLC_URL" == "ERROR" ]] || [[ "$APPVIEW_URL" == "ERROR" ]]; then + echo -e "${YELLOW}⚠️ Some tunnels failed to start. Check logs:${NC}" + echo " tail -f /tmp/ngrok-pds.log" + echo " tail -f /tmp/ngrok-plc.log" + echo " tail -f /tmp/ngrok-appview.log" + exit 1 +fi + +# Extract clean URLs (remove https://) +PDS_CLEAN=$(echo $PDS_URL | sed 's|https://||') +PLC_CLEAN=$(echo $PLC_URL | sed 's|https://||') +APPVIEW_CLEAN=$(echo $APPVIEW_URL | sed 's|https://||') + +echo -e "${CYAN}📱 Next Steps:${NC}" +echo "" +echo -e "1. Update ${YELLOW}coves-mobile/lib/config/environment_config.dart${NC}:" +echo "" +echo -e "${GREEN}static const local = EnvironmentConfig(${NC}" +echo -e "${GREEN} environment: Environment.local,${NC}" +echo -e "${GREEN} apiUrl: '$APPVIEW_URL',${NC}" +echo -e "${GREEN} handleResolverUrl: '$PDS_URL/xrpc/com.atproto.identity.resolveHandle',${NC}" +echo -e "${GREEN} plcDirectoryUrl: '$PLC_URL',${NC}" +echo -e "${GREEN});${NC}" +echo "" +echo -e "2. Run mobile app:" +echo -e " ${YELLOW}cd /home/bretton/Code/coves-mobile${NC}" +echo -e " ${YELLOW}flutter run --dart-define=ENVIRONMENT=local${NC}" +echo "" +echo -e "3. Login with:" +echo -e " Handle: ${CYAN}bob.local.coves.dev${NC}" +echo -e " Password: ${CYAN}bobpass123${NC}" +echo "" +echo -e "${YELLOW}💡 Tip: Leave this terminal open. Press Ctrl+C to stop tunnels.${NC}" +echo -e "${YELLOW} Or run: make ngrok-down${NC}" +echo "" + +# Keep script running (can be killed with Ctrl+C or make ngrok-down) +wait diff --git a/scripts/stop-ngrok.sh b/scripts/stop-ngrok.sh new file mode 100755 index 0000000..3b09e5c --- /dev/null +++ b/scripts/stop-ngrok.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Stop all ngrok tunnels + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +echo -e "${YELLOW}Stopping ngrok tunnels...${NC}" + +# Kill processes by PID if available +if [ -f /tmp/ngrok-pids.txt ]; then + PIDS=$(cat /tmp/ngrok-pids.txt) + for pid in $PIDS; do + kill $pid 2>/dev/null || true + done + rm /tmp/ngrok-pids.txt +fi + +# Fallback: kill all ngrok processes +pkill -f "ngrok http" || true + +# Clean up logs +rm -f /tmp/ngrok-*.log + +echo -e "${GREEN}✓ ngrok tunnels stopped${NC}" -- 2.51.2