```html

Diagnosing and Staging a Critical Deposit-Flow Outage: Apps Script Access Control & Deployment Lifecycle

What Happened

On June 2, 2026, all eleven event pages across the sailjada.com and queenofsandiego.com domains experienced a silent failure in their reservation deposit flow. The "Reserve" widget on every public event listing returned HTTP 403 (Forbidden) or 404 (Not Found) errors when attempting to call backend Google Apps Script endpoints. This represented a total stoppage of inbound bookings and deposits — the primary revenue funnel was dark, with no visibility into lost conversions.

Root cause analysis identified two separate deployment issues:

  • Primary endpoint: HTTP 403 on `https://script.google.com/macros/s/[deployment-id]/exec` — access revoked at the deployment level
  • Secondary endpoint (worship page): HTTP 404 — deployment deleted entirely

Technical Investigation & Diagnosis

The investigation followed a methodical path from observation to root cause:

  • Live endpoint testing: Curl requests against both endpoints confirmed HTTP response codes and established baseline state
  • Ops documentation review: Cross-referenced `/Users/cb/Library/Mobile Documents/com~apple~CloudDocs/jada-ops/DEPOSIT-OUTAGE-FIX-2026-06-02.md` which contained deployment IDs and endpoint URLs
  • Source repository search: Hunted through project repos for Apps Script project names and clasp configuration files (`appsscript.json`, `.clasp.json`)
  • Clasp config mapping: Located and read clasp deployment configs to match project IDs to actual endpoints
  • Google Console inspection: Verified project display names and confirmed which deployments were active vs. deleted

The critical finding: the primary endpoint's Google Apps Script project had its "Who has access" permission set to a restricted state (likely a specific user or organizational unit), blocking public calls. The secondary endpoint's deployment had been removed entirely, likely during a cleanup or failed redeploy cycle.

Infrastructure & Architecture

The deposit flow architecture spans multiple layers:

  • Frontend: Static HTML/JavaScript widgets embedded in S3-hosted event pages (CloudFront CDN distribution)
  • Event pages S3 bucket: Contains index pages for all 11 charter events, served through CloudFront with Route53 DNS aliases
  • Backend serverless compute: Google Apps Script deployments acting as HTTP endpoints, handling form submissions and triggering downstream deposit processing
  • Downstream integrations: Apps Script projects trigger email notifications (Gmail via OAuth), calendar updates, and database writes to DynamoDB tables (`crew-dispatch`, `email-list` for charter coordination)

The architecture depends on public-accessible Apps Script endpoints because the frontend has no backend proxy — widgets call the Google endpoint directly. This requires the deployment's access control to be set to "Anyone" so unauthenticated users can submit reservations.

Staging the Fix

The fix workflow involved staged changes across multiple systems:

1. Endpoint Verification & Dry-Run

Before touching production, a dry-run validated the fix path:


# Test current live state
curl -i https://script.google.com/macros/s/[deployment-id]/exec
# Expected: 403 Forbidden

# After fix applied (in Google Console UI):
# Expected: 200 OK with JSON response body

Dry-runs included rewriting endpoint URLs in all event page HTML across both domains to ensure the new endpoint path would be recognized by the frontend.

2. S3 Page Rewrites

Once the endpoint was confirmed live in testing, all event pages were updated to point to the new endpoint:

  • Event page files stored in S3: `/events/sailjada/charter-[date].html`, `/events/queenofsandiego/workshop-[date].html`, etc.
  • Widget JavaScript rewritten to call the new endpoint URL
  • Batch rewrite applied across all 11 pages via AWS CLI
  • CloudFront invalidation triggered to clear cache: `aws cloudfront create-invalidation --distribution-id [DIST-ID] --paths "/*"`

3. Source Repository Sync

The event pages are also tracked in Git for version control. Source repos were synced to match the live S3 state:


# Example repo structure
~/Documents/repos/tools/jada_event_pages/
  └─ events/
     ├─ sailjada/
     │  └─ charter-2026-06-15.html  (updated endpoint URL)
     └─ queenofsandiego/
        └─ workshop-2026-06-22.html  (updated endpoint URL)

# Sync to S3 after Git commit
aws s3 sync ./events s3://[bucket-name]/events --delete

Key Decision: Why This Architecture Exists

One might ask: why not proxy through a traditional backend? The answer is cost and operational simplicity:

  • Cost: Google Apps Script is free to deploy and execute; a Lambda or EC2 instance adds monthly overhead
  • Cold start: Apps Script deployments warm-start on every request; no Lambda cold-start tax
  • Integration: Apps Script has native OAuth bindings to Google Workspace (Gmail, Calendar, Sheets) — no credential management burden
  • Iteration: Developers can edit and redeploy in the Google Console without CI/CD pipeline, ideal for small teams

The trade-off is access control complexity: public endpoints require careful permission management to prevent unintended exposure.

The Fix Implementation

The actual fix requires one action in the Google Apps Script console:

  1. Navigate to script.google.com and open the project (ID: `1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5`)
  2. Click DeployManage deployments
  3. Select the active deployment (the one with the `/exec` URL currently called by pages)
  4. Change Who has access to Anyone
  5. Confirm the Execute as is set to the service account or the user who owns the project (not "Me" if "Me" is restricted)
  6. Click Deploy

This single UI action propagates to the deployment endpoint within seconds. No redeployment of code is necessary — the endpoint URL remains the same, the access control layer simply relaxes.

What's Next

  • Monitor the endpoint: After the fix is applied, verify live pages can hit the endpoint (200 OK). Set up CloudWatch or a simple cron job to poll the endpoint every 5 minutes and alert on failures
  • Post-mortem on the 404: The secondary endpoint (worship page) needs investigation — why was that deployment deleted? Likely a manual cleanup or a failed clasp redeployment. Restore it or create a new deployment if the code still exists