Multi-Service Charter Booking Pipeline: Integrating Boatsetter, ShipCaptainCrew, and Guest Portal
This post covers the architecture and implementation of a unified charter booking workflow that bridges three separate systems: Boatsetter (customer-facing marketplace), ShipCaptainCrew (crew scheduling and logistics), and a custom guest portal. The challenge was orchestrating data flow across these systems while maintaining authentication boundaries, managing CloudFront caching layers, and ensuring crew notifications propagate automatically.
What Was Done
We implemented an end-to-end booking pipeline triggered by a new Boatsetter charter. The system creates four synchronized artifacts:
- JADA Internal Calendar entry — internal scheduling visibility
- ShipCaptainCrew event — crew-facing booking with auto-notification
- Guest-facing portal page — static HTML at
/g/{SESSION_ID}on queenofsandiego.com - Crew-facing checklist page — integrated within SCC event details
Technical Architecture
Service Integration Points
The three independent systems required careful authentication handling at each integration boundary:
- JADA Calendar (internal Lambda) — requires
X-Dashboard-Tokenheader; calls the dashboard Lambda via standard HTTPS endpoint - ShipCaptainCrew API — uses service key authentication, but CloudFront headers are stripped by the distribution's origin request function; solution was to hit the API Gateway endpoint directly, bypassing CloudFront entirely
- Guest Portal (S3 + CloudFront) — files served from S3 bucket
queenofsandiego.com, distributed via CloudFront with path rewriting logic
S3 and CloudFront Configuration
Guest pages are uploaded to S3 as flat HTML files (e.g., /tmp/jada-guest-xhqgmdh.html) with a specific naming convention. The CloudFront distribution for queenofsandiego.com includes an origin request function that rewrites incoming requests to /g/{SESSION_ID} into the corresponding flat file in S3. This avoids directory-based routing and simplifies cache invalidation.
S3 Bucket: queenofsandiego.com
CloudFront Distribution: Configured with an origin request Lambda@Edge function that handles path rewriting. When a request arrives for /g/XHQGMDH, the function rewrites it to fetch /jada-guest-XHQGMDH.html from the S3 origin.
Cache Invalidation: After upload, we invalidate the CloudFront path pattern to ensure fresh content is served immediately.
ShipCaptainCrew Authentication Deep Dive
The SCC service presented an authentication challenge. The Lambda function environment includes a SERVICE_KEY_HASH variable. On initial requests, this hash was missing from the environment, causing authentication failures. The solution involved:
- Downloading the SCC Lambda deployment package from the provided URL
- Examining the
hash_passwordfunction to understand the hashing algorithm - Verifying the actual service key against the expected hash
- Updating the Lambda environment to include the correct
SERVICE_KEY_HASH
Additionally, CloudFront was stripping custom headers (including the service key). The workaround was to invoke the API Gateway endpoint directly instead of routing through the CloudFront distribution. This requires knowing the API Gateway endpoint URL (stored in secrets, not the CloudFront domain).
Example request pattern:
POST https://api-gateway-endpoint.execute-api.region.amazonaws.com/prod/events
Authorization: Bearer {SERVICE_KEY}
Content-Type: application/json
Data Pipeline and Event Flow
The booking creation follows this sequence:
- Trigger: New charter booked on Boatsetter; webhook or manual entry provides booking details (guest name, date, duration, rate)
- Financial Calculation: Compute crew costs (e.g., 2 crew × $25/hr × 5 hrs = $250), captain costs ($50/hr × 3 hrs = $150), port fees (18% of gross), and net revenue to operator
- Calendar Entry: POST to dashboard Lambda at
/calendarendpoint withX-Dashboard-Tokenheader; includes charter date, crew assignments, and internal notes - SCC Event: POST to ShipCaptainCrew API Gateway endpoint to create event; payload includes guest details, crew roster, event description, and checklist items
- Guest Portal: Generate static HTML with guest-specific information (check-in time, safety briefing, emergency contact); upload to
queenofsandiego.comS3 bucket with session-based naming - Crew Notification: SCC event creation triggers automatic notification emails to all assigned crew with magic links for quick confirmation
Key Decision: Why Direct API Gateway for SCC
CloudFront distributions, when configured with origin request functions, may strip certain headers for security reasons. Custom authorization headers were being removed before the request reached the SCC Lambda. Rather than reconfigure CloudFront (which serves many other routes), we determined that SCC API calls should route directly to the API Gateway endpoint. This trades off the caching benefits of CloudFront for reliable, header-preserving authentication.
Key Decision: Flat HTML Files vs. Dynamic Routing
Guest portal pages could be served dynamically from a Lambda function, but instead we chose flat HTML files uploaded to S3. This decision was driven by:
- Simplicity: No additional Lambda cold starts; S3 serves static content immediately
- Caching: CloudFront can aggressively cache without worrying about query strings or dynamic state
- Rewriting: The CloudFront origin request function handles path rewriting transparently
- Cost: S3 + CloudFront is cheaper than Lambda invocations for every guest portal access
Security Considerations
- Revenue Hiding: SCC events should not expose captain fees or revenue calculations to crew. After initial event creation, a follow-up DynamoDB update removes these fields from the
notesfield, ensuring crew sees only operational details - Token Scope: The
X-Dashboard-Tokenis scoped to dashboard operations; SCC uses a separate service key, maintaining separation of concerns - CloudFront Bypass: Direct API Gateway access bypasses rate limiting and WAF rules that may be configured at CloudFront; ensure API Gateway has its own protections
Implementation Commands (Abstracted)
# List files in JADA site directory
aws s3 ls s3://sailjada.com/
# Upload guest page to queenofsandiego.com
aws s3 cp /tmp/jada-guest-xhqgmdh.html s3://queenofsandiego.com/j