```html

Diagnosing and Resolving Multi-Site Deployment Issues: OAuth Token Failures and Booking Widget JavaScript Fixes

What Was Done

During this development session, we performed a comprehensive health check on the jada-agent orchestrator daemon (Lightsail instance 34.239.233.28), debugged OAuth authentication failures affecting Google Analytics API integrations, and resolved a critical JavaScript syntax error in the booking widget across multiple production sites.

The work spanned three distinct areas:

  • Remote daemon monitoring and service health verification via SSH and AWS Lightsail metrics APIs
  • Google Analytics 4 API authentication and data pipeline troubleshooting
  • Multi-site JavaScript deployment fixes affecting sailjada.com, 86from.com, and queenofsandiego.com

Daemon Health Assessment and Infrastructure Monitoring

The jada-agent.service orchestrator was verified to be healthy with 11 days of uptime and consistent performance metrics. Rather than relying on stored SSH keys (which were not available locally), we authenticated using AWS Lightsail's temporary SSH certificate API:

# Retrieve temporary SSH access credentials from Lightsail API
# Then verify service status and collect metrics
systemctl status jada-agent.service
journalctl -u jada-agent.service -n 200 --no-pager
ps aux | grep jada-agent
free -h
df -h

Key findings:

  • Service Status: Active and running since May 10 (3 days continuous uptime)
  • Resource Utilization: CPU averaged 0.65% (normal for polling), memory at 144MB/914MB, disk at 17% capacity (6.2GB/39GB)
  • Session Usage: 3 of 5 daily sessions consumed as of the check time; two sessions hit the 30-turn Claude context limit (expected behavior for complex multi-task sessions)
  • Task Processing: Session 2 completed successfully and processed e-signature and crew page generator blockers, creating a needs-you task for manual review

AWS Lightsail CloudWatch metrics were also queried directly to confirm status checks passed (zero failures in the previous 2 hours), network I/O was minimal, and no CPU spikes were recorded.

Google Analytics OAuth Token Failure Diagnosis

While verifying daemon health, we discovered that the port_sheet_sync.py script was experiencing repeated authentication failures:

[port-sheet] token error: HTTP Error 400: Bad Request

This error appeared consistently every 30 minutes in the daemon logs, indicating the Google OAuth token used for the port sheet synchronization had expired or been revoked. The root cause was token staleness—the OAuth2 refresh token stored for the dangerouscentaur@gmail.com account in the jada-agent credentials store was no longer valid.

Token Management Architecture:

The authentication flow uses a two-stage approach:

  • Initial Auth: /Users/cb/Documents/repos/tools/auth_ga.py handles the OAuth2 authorization code grant flow, storing credentials in a JSON token file
  • Token Reuse: Scripts like port_sheet_sync.py read the stored token, use the refresh token to obtain new access tokens as needed, and cache the token locally
  • Scope Isolation: The script requires Google Analytics Data API, Sheets API, and Drive API scopes

During the session, we verified that google-auth-oauthlib and the Google Auth library were installed, confirmed that the client ID and client secret existed in the stored token (allowing token reuse), and confirmed that the jada-agent account had access to GA4 properties under the dangerouscentaur account (verified by listing GA4 accounts and pulling a 7-day analytics report from the 86dfrom.com property).

The fix required re-authenticating the Google OAuth token for the port_sheet_sync.py workflow. This task was added to the needs-you queue for manual execution when the auth script becomes available.

JavaScript Booking Widget Fixes and Multi-Site Deployment

The most extensive work involved fixing a template variable syntax error in the booking widget JavaScript that was deployed across three production sites. The booking widget code was using double-brace syntax {{ variable }} that was being interpreted as Jinja2/Django template variables rather than JavaScript variables.

Sites Affected:

  • /Users/cb/Documents/repos/sites/sailjada.com/index.html (15+ edits)
  • /Users/cb/Documents/repos/sites/queenofsandiego.com/BookingAutomation.gs (2 edits)
  • /Users/cb/Documents/repos/sites/86from.com/site/index.html (3 edits)

Root Cause Analysis: The booking widget section contained JavaScript like:

const bookingConfig = {
  widgetId: "{{ booking_widget_id }}",
  merchantId: "{{ merchant_id }}"
};

When these files were processed through a template engine, the double braces conflicted with the templating syntax. The solution was to replace double braces with single braces within the booking widget block only, preserving the original syntax in all other parts of the document:

const bookingConfig = {
  widgetId: "{ booking_widget_id }",
  merchantId: "{ merchant_id }"
};

Verification Process:

  • Extracted the booking widget JavaScript block (identified by line numbers)
  • Syntax-checked the entire block using Node.js to confirm valid JavaScript
  • Verified no double-brace occurrences remained within the widget section
  • Confirmed double braces outside the widget section were left untouched

Deployment Strategy:

  • sailjada.com: Updated /index.html and deployed via S3 bucket sync, followed by CloudFront cache invalidation
  • queenofsandiego.com: Updated /BookingAutomation.gs (Google Apps Script), deployed directly to Google Sheets backend
  • 86from.com: New property created (directory renamed from 86dfrom.com to 86from.com/what-does-86d-mean) added

A version tag with model ID was embedded into the booking widget JavaScript comment block to allow rapid identification of deployed versions in the dashboard.

Site Infrastructure and Content Updates

The 86dfrom.com property underwent significant changes:

  • Directory Rename: Moved from /Users/cb/Documents/repos/sites/86dfrom.com to /Users/cb/Documents/repos/sites/86from.com to match the actual domain
  • S3 Deployment: Synced to the 86from.com S3 bucket with appropriate bucket policy and public-read ACL