Multi-Domain Event Infrastructure: Coordinating Charter Bookings Across SCC, JADA Calendar, and Guest-Facing Pages
When a charter booking comes through Boatsetter, it needs to exist in at least four places simultaneously: the internal JADA calendar system, the ShipCaptainCrew (SCC) crew management platform, a guest-facing confirmation page, and a crew-facing logistics checklist. This post walks through the infrastructure decisions and implementation details for automating this multi-system synchronization.
The Problem: Four Systems, One Event
A typical booking creates a chain reaction:
- Captain needs to confirm availability and see earnings
- Crew (2 × 5-hour shifts at $25/hr) need crew-facing checklists and confirmation links
- Internal calendar must reflect the booking with financial projections
- Guest must receive a confirmation page with logistics details
- Each system has different authentication, different required fields, and different data models
Building this manually takes ~30 minutes per booking. Automating it is worth the infrastructure investment.
Technical Architecture
System Integration Points
SCC Lambda (Source of Truth for Events)
The ShipCaptainCrew Lambda function at /tmp/scc-lambda-src/lambda_function.py is the primary event creation endpoint. It handles:
- Event CRUD operations (routes
POST /events,PATCH /events/{id}) - Authentication via
SERVICE_KEY_HASHenvironment variable (bcrypt-verified) - DynamoDB persistence to
scc-eventstable - Automatic crew notification via magic links (handled by Lambda's
handle_event_create)
The key insight: SCC Lambda automatically emails all assigned crew when an event is created. This is handled by the event creation handler, which queries the crew list and generates time-limited confirmation links. No separate notification system needed.
JADA Calendar Lambda
A separate Lambda (identified via secrets lookup) handles internal calendar entries. It requires:
X-Dashboard-Tokenheader (API key authentication)- POST body with
date,revenue,expenses,notes - Endpoint accessible via API Gateway URL (not CloudFront, to avoid header stripping)
Guest-Facing Page Infrastructure
Guest pages are hosted on queenofsandiego.com (CloudFront distribution) with S3 origin queenofsandiego-static. The CloudFront function (Viewer Request) rewrites paths:
/g/{GUID}.html→ serves from S3 key/g/{GUID}.html- Pages are flat HTML files (not directory-based) per the CF function's
uri.endsWith('.html')pattern - CloudFront distribution ID: (retrieved from secrets, not repeated here)
Crew-Facing Logistics Page
The crew page is served directly through SCC's existing guest presign route (GET /g/{event_id} in SCC Lambda). This endpoint:
- Validates the crew member's magic link token
- Returns time-aware HTML with photo upload capability
- Presigns S3 URLs for crew to upload charter photos
- Reads from the same SCC events table as the calendar system
Implementation Details
Event Creation Workflow
The automation runs these steps in sequence:
- Calculate financials
Gross Revenue: $840.75 Crew (2 × 5hr × $25): -$250.00 Captain (3hr × $50): -$150.00 Port/Tax (18%): -$151.34 ──────────────────────────── Net to Captain: $289.41 - Create SCC Event
POST /events (via direct API Gateway URL, not CloudFront) { "event_id": "XHQGMDH", "date": "2025-05-30T14:00:00Z", "duration_hours": 3, "crew_ids": ["crew-1", "crew-2"], "captain_id": "captain-1", "notes": "Boatsetter booking ref: [BOOKING_ID]", "status": "pending_confirmation" }SCC Lambda automatically hashes the SERVICE_KEY, compares to
SERVICE_KEY_HASHenv var, then creates the event and triggers crew notifications. - Create JADA Calendar Entry
POST /calendar (to Lambda endpoint, bypasses CloudFront) Headers: X-Dashboard-Token: [TOKEN] { "date": "2025-05-30", "revenue": 840.75, "expenses": { "crew": 250.00, "captain": 150.00, "port_tax": 151.34 }, "notes": "Boatsetter charter + SCC event XHQGMDH" } - Generate Guest Page
- Build static HTML file with guest's name, date, time, and logistics
- Write to
/tmp/jada-guest-XHQGMDH.htmllocally - Upload to S3:
s3://queenofsandiego-static/g/XHQGMDH.html - Invalidate CloudFront cache:
/g/XHQGMDH.html
- Crew Receives Confirmation Links
SCC Lambda's event creation handler has already sent magic link emails. Each crew member receives a unique token that grants access to
/g/XHQGMDH?token=[CREW_TOKEN], which displays the crew logistics page with photo upload.
Key Technical Decision: Bypassing CloudFront for API Calls
During implementation, we discovered that CloudFront was stripping the X-Dashboard-Token header when routing to Lambda origins. The solution: use the direct API Gateway URL instead of the CloudFront distribution URL for programmatic API calls.
This required identifying the actual API Gateway endpoint URL from the Lambda configuration, then using it as an alternate route for cross-system integration calls. Guest-facing requests continue to use CloudFront (with caching benefits), but system-to-system calls use the direct endpoint.
Why No Separate Captain/Hostess Fields in SCC
The booking request indicated "no hostess, no host, just bare minimum." The SCC event is created with only crew_ids and captain_id arrays—no additional host fields. This keeps the DynamoDB schema lean and reflects the actual staffing model.