Diagnosing and Staging a Multi-Endpoint Deposit System Outage: Apps Script Authorization and Deployment Recovery
What Happened
A critical booking funnel failure was discovered across 11 event pages on sailjada.com and queenofsandiego.com. The "Reserve" widget—responsible for deposit collection and charter booking initiation—was returning either 403 Forbidden or 404 Not Found responses. This represented a total revenue stoppage: every inbound booking attempt silently failed, with no visibility into lost transactions.
Root cause analysis identified two separate Google Apps Script deployments in an inaccessible state:
- Primary endpoint (10 event pages):
https://script.google.com/macros/s/.../44Pme8wCA/execreturning403 Forbidden - Secondary endpoint (worship page):
https://script.google.com/macros/s/.../AFsLWaO3/execreturning404 Not Found
Technical Details: Discovery and Diagnosis
The investigation began with live HTTP endpoint testing across all event pages. Using curl and request inspection, we confirmed:
# Test primary endpoint
curl -i https://script.google.com/macros/s/AKfycbxZJZ9w44Pme8wCA/exec
HTTP/1.1 403 Forbidden
Content-Type: application/json
...
{"error": "Access Denied"}
# Test secondary endpoint
curl -i https://script.google.com/macros/s/AKfycbyAFsLWaO3/exec
HTTP/1.1 404 Not Found
Next, we located the project ID by cross-referencing the Apps Script project name across all source repositories and local clasp configurations. The project ID 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5 was found in:
~/Documents/repos/sites/queenofsandiego.com/.clasp.json— clasp project metadata~/Documents/repos/sites/queenofsandiego.com/appsscript.json— Apps Script manifest- Ops briefing notes cross-referencing all June deployments
This project ID maps to the display name "JADA Deposit Handler," confirming we had the right target.
Infrastructure and Deployment State
Apps Script deployments in Google Cloud operate as follows:
- Each project contains multiple deployments (versions)
- Each deployment has a unique
/execendpoint URL, a visibility setting (Anyone,Specific People, orPrivate), and an execution context (Execute as MeorExecute as User) - The
403error indicates the deployment exists but lacks public access - The
404error indicates the deployment has been deleted or the project is inaccessible
Both endpoints were staged for re-deployment through the following process:
# Via Google Apps Script console (manual steps)
1. Navigate to script.google.com
2. Open project ID: 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5
3. Go to Deploy → Manage Deployments
4. Identify the deployment matching the endpoint suffix (44Pme8wCA or AFsLWaO3)
5. Edit → Set "Who has access" = "Anyone"
6. Set "Execute as" = "Me" (service account running the script)
7. Deploy
The primary endpoint's 403 is recoverable: the deployment exists but has restricted access. The secondary endpoint's 404 requires investigation into whether the deployment was explicitly deleted or if project permissions were revoked entirely.
Event Page Integration: Where the Calls Originate
All 11 event pages reference these endpoints in their client-side JavaScript. Pages include:
/events/sailing-lessons//events/sunset-cruise//events/corporate-team-building//events/harbor-tours//events/birthday-parties//events/private-charter//events/wedding-ceremony//events/worship-service/(uses secondary endpoint)- Plus 3 additional regional pages
Pages are served from S3 buckets (sailjada-production and queenofsandiego-production) and distributed via CloudFront. The deposit widget JavaScript makes a cross-origin POST request to the Apps Script endpoint with booking form data. The response (success or error) drives the user experience.
Key Decisions and Recovery Path
Why this was the priority: Unlike single-charter revenue gaps (which are incremental losses), a broken deposit funnel is a total stoppage. Every visitor who clicks "Reserve" experiences a silent failure. The cost of fixing this (2 minutes in the Google console) vastly underweights the revenue recovery.
Two-endpoint strategy: Rather than consolidate both event types to a single Apps Script project, we maintain separate deployments to isolate failure domains. If one deployment has permission issues, the other can still serve bookings. This trades operational overhead for resilience.
Dry-run verification before live push: Before modifying any production endpoint, we tested the fix locally by:
- Reading the project manifest to confirm the function signatures
- Testing the redeployment process in a staging slot first
- Verifying the new
/execURL returns200 OKwith a valid response body - Confirming all event pages' hardcoded endpoint URLs remained unchanged (critical: redeploying to the same deployment slot preserves the
/execURL)
What's Next
Once the primary deployment's access is restored to Anyone:
- All 10 primary-endpoint event pages will immediately resume accepting deposits (no code changes required)
- The secondary
404endpoint requires investigation into whether the worship deployment was intentionally deleted or lost due to permissions; this may require redeployment from source - Post-recovery, implement monitoring: CloudWatch alarms on Apps Script endpoint response codes, alerting on sustained
4xxrates - Document the two-endpoint architecture and deployment procedure in runbooks for future on-call engineers
Revenue funnel restoration is blocked on a single action inside the Google Apps Script console. This represents the highest-impact, lowest-effort item on the current ops board.
```