```html

Diagnosing and Staging a Critical Deposit Booking Outage: Apps Script Access Control & Deployment Recovery

What Happened

A production outage left the deposit/booking functionality on 11 event pages completely non-functional. Every "Reserve" widget across sailjada.com and queenofsandiego.com was silently failing—users attempting to make deposits hit dead endpoints returning either 403 (Forbidden) or 404 (Not Found). The root cause: two Google Apps Script deployments had lost their public execution permissions and one had been deleted entirely.

Why This Mattered

Unlike a degraded feature, a total booking funnel failure is invisible revenue loss. No error message reaches users; they simply see a broken button. With zero observability into the failure rate, the business impact was unknown—every inbound reservation attempt was being silently dropped. This is the type of incident that demands immediate diagnosis and fix, not incremental improvement.

Technical Diagnosis Process

1. Endpoint Mapping & Live Testing

The first step was identifying which Apps Script deployments were actually being called:

  • Located all event page HTML files in /Documents/repos/sites/queenofsandiego.com/events/ and /Documents/repos/sites/sailjada.com/events/
  • Grep'd across all 11 pages for the Apps Script endpoint URLs being invoked
  • Found two distinct deployment endpoints in use:
    • Primary (10 pages): https://script.google.com/macros/s/AKfycbx...44Pme8wCA/exec — returning 403 Forbidden
    • Worship page: https://script.google.com/macros/s/AKfycbx...AFsLWaO3/exec — returning 404 Not Found
  • Tested both endpoints with curl to confirm live status; both were inaccessible

2. Project Identification

The endpoint URL slugs don't directly map to project IDs visible in script.google.com. To identify which projects owned these deployments:

  • Read all .clasp.json config files in the source repos to find registered Apps Script project IDs
  • Cross-referenced the project ID 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5 against the jada-ops notes
  • Confirmed this project contained both deployments and was the source of the "Reserve" widget code
  • Accessed the project directly via script.google.com and navigated to Deploy → Manage deployments

3. Access Control Analysis

Once inside the project's deployment dashboard, the issue became clear:

  • Primary deployment (44Pme8wCA): existed but had "Who has access" set to a restricted list (likely only the original developer's account)
  • Worship deployment (AFsLWaO3): had been deleted or undeployed entirely, leaving orphaned endpoint URLs on the live pages

This is a common post-handoff problem: when a project is shared but deployments aren't re-shared with public access, the endpoints go dark for unauthenticated traffic.

Staging the Fix

Primary Deployment Redeploy

The fix for the 403 status requires a single change in the Google Apps Script console:

  1. Open the project in script.google.com
  2. Navigate to Deploy → Manage deployments
  3. Click the primary deployment (44Pme8wCA)
  4. Set the dropdown:
    • Who has access: "Anyone"
    • Execute as: Me (the project owner's service account)
  5. Click Deploy

This single action redeploys the Apps Script function with public execution permission, allowing unauthenticated HTTP calls from the event pages to succeed. The deployment ID stays the same, so no page code changes are required.

Worship Deployment Recovery

For the 404, the deployment was deleted. Two recovery paths:

  • Path A (faster): Create a new deployment from the existing project code. The deployment URL will change, requiring a one-line edit on the worship page HTML to point to the new endpoint.
  • Path B (cleaner): If the project has version history, restore to a prior version where both deployments existed, then re-deploy both.

The staged approach documents the exact steps but does not execute them until you approve, to avoid any unintended side effects.

Infrastructure & Architecture Notes

Event Page Stack

The 11 event pages are static HTML files stored in source repos and deployed via S3 + CloudFront:

  • Source: /Documents/repos/sites/queenofsandiego.com/events/ and /Documents/repos/sites/sailjada.com/events/
  • Hosting: S3 buckets (static assets), fronted by CloudFront CDN
  • Reserve widget: inline JavaScript that calls the Apps Script /exec endpoint to process deposits

Because the endpoint URLs are hardcoded in the HTML, changes to Apps Script deployments require either:

  • Editing the HTML and re-deploying to S3, or
  • Redeploying the Apps Script to the same deployment slot (preserving the URL)

The staged fix does the latter for the primary deployment, minimizing changes.

Why the 403 Happened

Apps Script deployments default to restricting access to the project owner and explicitly-shared users. When a deployment is created but not published with "Anyone" access, HTTP calls from external sources fail with 403. This often occurs when:

  • A developer creates a deployment for testing
  • The project is handed off to a new owner
  • The new owner assumes the deployment is already public (it isn't)

Key Decisions

  • Prioritize the deposit outage first: Total funnel stoppage beats all other work. No observable limits on losses, so fix immediately.
  • Use the same deployment ID: Avoids cascading HTML edits across 11 pages and multiple repos. Redeploy to the existing slot rather than create new deployments.
  • Execute as project owner: Ensures the Apps Script code runs with the owner's permissions, allowing it to access Google Sheets, Calendar, Gmail, etc., as needed by the Reserve widget.
  • Stage but don't auto-apply: Document the exact steps so you (the owner) can apply the fix directly in the Google console. This avoids scripting away visibility into what changed.

What's Next