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
18 changes: 18 additions & 0 deletions .cloudflared/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Cloudflare Tunnel Configuration
# This configures a named tunnel for development access via tunnel.cambeerfestival.app
#
# Setup instructions:
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Run the tunnel: cloudflared tunnel run cbf-dev-tunnel
#
Comment on lines +5 to +9

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The setup instructions in the comments reference manual cloudflared commands, but developers are expected to use the tunnel-setup mise task instead. The comments should be updated to reference the mise task for consistency:

# Setup instructions:
# Run the automated setup: MISE_ENV=dev ./bin/mise run tunnel-setup
#
# Or set up manually:
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Update credentials-file path below with your tunnel UUID
# 5. Run the tunnel: MISE_ENV=dev ./bin/mise run dev-tunnel
Suggested change
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Run the tunnel: cloudflared tunnel run cbf-dev-tunnel
#
# Recommended: Run the automated setup task:
# MISE_ENV=dev ./bin/mise run tunnel-setup
#
# Or set up manually (if needed):
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Update the credentials-file path below with your tunnel UUID
# 5. Run the tunnel: MISE_ENV=dev ./bin/mise run dev-tunnel
#

Copilot uses AI. Check for mistakes.
# The tunnel UUID and credentials will be stored in ~/.cloudflared/ after creation

tunnel: cbf-dev-tunnel
credentials-file: /home/vscode/.cloudflared/be8d5634-735e-4637-b030-6f818e739b77.json
Comment on lines +11 to +13

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded UUID in the credentials file path (be8d5634-735e-4637-b030-6f818e739b77.json) appears to be developer-specific and will differ for each developer who runs cloudflared tunnel create. This will cause the tunnel to fail for other developers.

The tunnel-setup task creates a tunnel, which generates a unique UUID for each tunnel instance. Since this UUID is different for every developer, the config file should either:

  1. Use a dynamic path that cloudflared can resolve automatically, or
  2. Include instructions in the config file comments for developers to update this value after running tunnel-setup, or
  3. Have the tunnel-setup task automatically update the config file with the correct UUID

Option 3 would provide the best developer experience.

Suggested change
tunnel: cbf-dev-tunnel
credentials-file: /home/vscode/.cloudflared/be8d5634-735e-4637-b030-6f818e739b77.json
# The credentials file is auto-resolved by cloudflared; do not hardcode the path.
tunnel: cbf-dev-tunnel

Copilot uses AI. Check for mistakes.

ingress:
- hostname: tunnel.cambeerfestival.app
service: http://localhost:8080
- service: http_status:404
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
mise.local.toml
mise.*.local.toml

# Cloudflare Tunnel
.cloudflared/*.json
.cloudflared/cert.pem

# Flutter repo-specific
/bin/cache/
/bin/internal/bootstrap.bat
Expand Down
12 changes: 12 additions & 0 deletions cloudflare-worker/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const ALLOWED_ORIGINS = [
'https://richardthe3rd.github.io',
'https://cambeerfestival.app',
'https://staging.cambeerfestival.app',
'https://tunnel.cambeerfestival.app',
'http://localhost:8080',
'http://localhost:3000',
'http://127.0.0.1:8080',
Expand Down Expand Up @@ -236,6 +237,17 @@ function getCorsHeaders(request) {
};
}

// Allow Cloudflare Tunnel quick tunnels (*.trycloudflare.com)
// Used for local development with cloudflared tunnel
// Security note: These are temporary development tunnels controlled by Cloudflare.
// Only enable this in development/staging workers, not production.
if (origin.endsWith('.trycloudflare.com')) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Credentials': 'true',
};
}

Comment on lines +240 to +250

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wildcard CORS allowance for *.trycloudflare.com is being added to the worker without any environment checks. According to the security note in the comment, this should "only enable this in development/staging workers, not production."

However, looking at cloudflare-worker/wrangler.toml, there's only one worker environment configured (ENVIRONMENT = "production"), and this worker is deployed directly to production via the GitHub workflow when changes are merged to main.

This creates a security risk where the production worker will allow CORS from any *.trycloudflare.com origin, which could potentially be exploited.

Recommended solutions:

  1. Remove this wildcard allowance if there's no separate dev/staging worker deployment, or
  2. Set up separate worker environments (dev/staging/production) with different CORS configurations, or
  3. Add runtime environment checks in the worker code to only enable this for non-production environments
Suggested change
// Allow Cloudflare Tunnel quick tunnels (*.trycloudflare.com)
// Used for local development with cloudflared tunnel
// Security note: These are temporary development tunnels controlled by Cloudflare.
// Only enable this in development/staging workers, not production.
if (origin.endsWith('.trycloudflare.com')) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Credentials': 'true',
};
}

Copilot uses AI. Check for mistakes.
// Reject all other origins by not including CORS headers
return {};
}
Expand Down
71 changes: 71 additions & 0 deletions mise.dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,75 @@ url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d
[macos-x64]
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{version}/darwin-x64/claude"
""", version_list_url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/stable" }
cloudflared = "latest"
"npm:firebase-tools" = "14.26.0" # Pin to a stable version for reproducibility

[tasks.dev]
run = '''
echo "Starting Flutter dev server on http://localhost:8080"
flutter run -d web-server --web-port 8080
'''

[tasks.tunnel-setup]
run = '''
echo "Setting up Cloudflare Tunnel for tunnel.cambeerfestival.app"
echo ""

# Check if already logged in
if [ ! -f ~/.cloudflared/cert.pem ]; then
echo "Step 1: Login to Cloudflare (browser will open)..."
cloudflared tunnel login
else
echo "✓ Already logged in to Cloudflare"
fi

# Check if tunnel already exists
if cloudflared tunnel list 2>/dev/null | grep -q "cbf-dev-tunnel"; then
echo "✓ Tunnel 'cbf-dev-tunnel' already exists"
else
echo ""
echo "Step 2: Creating tunnel 'cbf-dev-tunnel'..."
cloudflared tunnel create cbf-dev-tunnel
fi

# Route DNS
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
Comment on lines +53 to +55

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DNS routing step runs unconditionally on every tunnel-setup execution, which could cause issues or confusion if the route already exists. Consider adding a check similar to the tunnel existence check:

# Check if DNS route already exists
if cloudflared tunnel route list 2>/dev/null | grep -q "tunnel.cambeerfestival.app"; then
  echo "✓ DNS route for tunnel.cambeerfestival.app already exists"
else
  echo ""
  echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
  cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
fi

This prevents duplicate route creation attempts and provides clearer feedback to developers.

Suggested change
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# Check if DNS route already exists
if cloudflared tunnel route list 2>/dev/null | grep -q "tunnel.cambeerfestival.app"; then
echo "✓ DNS route for tunnel.cambeerfestival.app already exists"
else
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
fi

Copilot uses AI. Check for mistakes.

echo ""
echo "✅ Setup complete! You can now run: MISE_ENV=dev ./bin/mise run dev-tunnel"
'''

[tasks.dev-tunnel]
run = '''
# Start Cloudflare Tunnel in the background
echo "Starting Cloudflare Tunnel..."
cloudflared tunnel --config .cloudflared/config.yml run &
TUNNEL_PID=$!

# Wait for tunnel to be ready
echo "Waiting for tunnel to start..."
sleep 3

echo ""
echo "✅ Tunnel running at: https://tunnel.cambeerfestival.app"
echo ""
echo "Starting Flutter dev server on http://localhost:8080"
echo "Press Ctrl+C to stop both services."
echo ""

# Cleanup function
cleanup() {
echo ""
echo "Stopping tunnel..."
kill $TUNNEL_PID 2>/dev/null
Comment on lines +68 to +83

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dev-tunnel task uses kill $TUNNEL_PID 2>/dev/null which may not properly clean up the cloudflared process if it has spawned child processes. Consider using kill -- -$TUNNEL_PID to kill the entire process group, or use a more robust cleanup mechanism.

Additionally, the 3-second sleep is arbitrary and may not be sufficient for the tunnel to fully start, especially on slower systems. Consider adding a retry loop that checks if the tunnel is actually responding:

# Wait for tunnel to be ready
echo "Waiting for tunnel to start..."
max_attempts=10
attempt=0
while ! curl -s -o /dev/null -w "%{http_code}" https://tunnel.cambeerfestival.app/health | grep -q "200"; do
  attempt=$((attempt + 1))
  if [ $attempt -ge $max_attempts ]; then
    echo "Tunnel failed to start after ${max_attempts} seconds"
    kill $TUNNEL_PID 2>/dev/null
    exit 1
  fi
  sleep 1
done

Copilot uses AI. Check for mistakes.
exit
}

# Set up cleanup on exit
trap cleanup EXIT INT TERM

# Run Flutter in foreground (so you can use 'r' for hot reload, etc.)
flutter run -d web-server --web-port 8080
'''
3 changes: 0 additions & 3 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,3 @@ echo "To view HTML report, install lcov and run: genhtml coverage/lcov.info -o c

[tasks.analyze]
run = 'flutter analyze --no-fatal-infos'

[tasks.dev]
run = 'flutter run -d web-server --web-port 8080'
Loading