```html

Diagnosing and Staging a Critical Deposit Outage: Apps Script Access Control and Multi-Endpoint Deployment Strategy

What Happened

During routine operations monitoring, all eleven event-booking pages across sailjada.com and queenofsandiego.com returned HTTP 403 and 404 errors on their deposit/reserve endpoints. The funnel was dark: inbound booking requests silently failed, revenue leakage was invisible, and the root cause required tracing back through three layers of indirection—from S3-hosted HTML, through CloudFront cache invalidation, to the actual Google Apps Script deployments.

Technical Investigation

Layer 1: S3 and CloudFront Verification

The investigation started by confirming that the event pages themselves were being served correctly from S3. Using the AWS CLI, we listed the contents of the primary events bucket and verified CloudFront distribution cache behavior:

aws s3 ls s3://queenofsandiego-events/ --recursive | grep -E "\.html$"
aws cloudfront list-distributions --query 'DistributionList.Items[?Comment==`events-cdn`]' --output table

The pages were in place and CloudFront was serving them. The failure was downstream: the inline <form> elements posting to external Google Apps Script endpoints were receiving authentication errors.

Layer 2: Endpoint URL Mapping

Each event page contains embedded reserve forms with action attributes pointing to Apps Script /exec endpoints. We mapped these:

  • Primary endpoint (10 pages): https://script.google.com/macros/s/AKfycbw.../44Pme8wCA/exec → returning HTTP 403 Forbidden
  • Worship endpoint (1 page): https://script.google.com/macros/s/AKfycbw.../AFsLWaO3/exec → returning HTTP 404 Not Found

The 403 indicated access control misconfiguration; the 404 suggested the deployment had been deleted or never properly deployed.

Layer 3: Google Apps Script Deployment Audit

Using Google Cloud Console access logs and the Apps Script dashboard, we identified that both deployments existed in the project (1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5) but had divergent access configurations:

  • Primary deployment: Access set to a specific user or organization domain, not "Anyone"
  • Worship deployment: Either deleted or never executed after the last code push

Root Cause Analysis

Apps Script deployments require explicit access control settings. The primary endpoint had its "Who has access" permission set to something more restrictive than "Anyone," blocking anonymous form submissions from the public reserve widget. The worship endpoint's 404 suggested either a failed deployment or a stale cached URL—both fixable with a fresh deployment that explicitly sets execute-as and access permissions.

The fix is not a code change; it's a deployment configuration change in the Google Apps Script console.

Staged Resolution

Remediation Steps (Not Yet Applied)

To restore both endpoints, the following changes are documented in /jada-ops/DEPOSIT-OUTAGE-FIX-2026-06-02.md:

  1. Open Google Apps Script project 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5 in script.google.com
  2. Navigate to Deploy → Manage Deployments
  3. Select the primary deployment (the one serving 44Pme8wCA)
  4. Set "Who has access" = Anyone
  5. Set "Execute as" = Me (the account owner running the script)
  6. Click Deploy
  7. For the worship deployment: If missing, create a new deployment from the existing code with the same access settings

These are one-click changes in the Google UI—no code deployment, no CI/CD pipeline, no DNS or CDN modifications required.

Why This Architecture Matters

The reserve system uses a three-tier pattern:

  • Tier 1 (Content): Static HTML hosted on S3, distributed via CloudFront
  • Tier 2 (Forms): Client-side form submission to external endpoint
  • Tier 3 (Backend): Google Apps Script as a lightweight, zero-ops function runner

This design avoids maintaining backend servers for booking logic. However, it creates a hard dependency on the Apps Script deployment being publicly accessible. A misconfigured access control doesn't fail gracefully—it silently blocks the entire booking funnel.

Testing and Validation Plan

Once the deployment access is corrected, verification involves:

# Test primary endpoint
curl -X POST https://script.google.com/macros/s/AKfycbw.../44Pme8wCA/exec \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data "eventName=TestEvent&depositAmount=100"

# Test worship endpoint  
curl -X POST https://script.google.com/macros/s/AKfycbw.../AFsLWaO3/exec \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data "eventName=TestEvent&depositAmount=100"

Both should return HTTP 200 with a success JSON response, not 403/404.

Impact and Next Steps

Impact: This outage affects all inbound deposits across 11 active event pages. No bookings can be completed. Revenue leak is unknown but real.

Next Steps:

  1. Apply the deployment fix in Google Apps Script console (2-minute task)
  2. Verify both endpoints return 200 with curl
  3. Run synthetic booking test through one of the event pages
  4. Monitor webhook/email notifications to confirm deposits are processing
  5. Post-incident: implement CloudWatch or Datadog alerts on Apps Script endpoint HTTP status to catch similar issues within minutes, not hours

The fix is straightforward and immediately unblocks revenue. It requires no code changes and no coordination with external teams—just access to the Google Apps Script project console.

```