```html

Diagnosing and Staging a Critical Deposit Endpoint Outage: Apps Script Access Control Recovery

During a routine deployment audit on June 2, 2026, we discovered that all 11 event pages across the Sail Jada platform were serving broken "Reserve" widgets—silent failures in the deposit funnel affecting every inbound booking attempt. This post covers the diagnosis methodology, infrastructure investigation, and the staged fix for a 403/404 endpoint outage on our Google Apps Script deployment.

The Problem: Silent Deposit Funnel Failure

End users hitting sailjada.com or queenofsandiego.com event pages encountered non-functional reserve buttons. The issue wasn't visible in logs because the failure was upstream—at the Apps Script deployment layer, not in our application code. This represented a total stoppage on revenue inbound, not a single-charter issue.

Live endpoint states discovered:

  • Primary deposit endpoint: https://script.google.com/macros/s/.../44Pme8wCA/exec → HTTP 403 (access revoked)
  • Worship event endpoint: https://script.google.com/macros/s/.../AFsLWaO3/exec → HTTP 404 (deployment deleted)

Diagnosis: Tracking Project Identity Across Deployment Layers

The first challenge was mapping the deployed Apps Script project to its source code and configuration. We worked through three levels of indirection:

Step 1: Identify the Project from Live Endpoints

We extracted the deployment ID from the live /exec URL and searched across infrastructure:

grep -r "44Pme8wCA" ~/jada-ops/
grep -r "44Pme8wCA" ~/code/jada-source/

This search located references in the outage documentation but not in active source repos, indicating the project was either archived or deployed from a different branch.

Step 2: Locate Project via Apps Script Config Files

We inspected .clasp.json files across all local source repositories to find which project matched:

find ~/code -name ".clasp.json" -exec cat {} \;
find ~/code -name "appsscript.json" -exec grep -l "displayName" {} \;

This revealed the project ID: 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5

Step 3: Cross-Reference Deployment vs. Project ID

Critical insight: the project ID and the deployment ID are different. The project ID is stable; deployment IDs change with each redeploy. Our 403 error was on a deployment that existed but had its sharing permissions revoked. The 404 on the worship endpoint indicated that specific deployment had been deleted entirely, likely from a cleanup or failed redeploy.

Root Cause Analysis: Access Control and Deployment State

Apps Script deployments exist in Google's infrastructure with metadata including:

  • Deployment ID — the unique identifier in the /exec URL
  • Access level — "Anyone," "Specific users," or "Only me"
  • Execute as — the identity under which the deployed function runs (user or service account)
  • Active status — whether the deployment is live or marked for deletion

The primary endpoint's 403 meant the deployment existed but access had been restricted—likely during a security audit or permission sync. The worship endpoint's 404 meant the deployment had been fully removed, requiring a complete redeploy.

Infrastructure Changes and Staging

Documented in: ~/Library/Mobile Documents/com~apple~CloudDocs/jada-ops/DEPOSIT-OUTAGE-FIX-2026-06-02.md

We staged the fix without applying it immediately (following deployment discipline):

For the primary 403 endpoint:

  • Navigate to script.google.com → Project 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5
  • Open Deploy → Manage deployments
  • Select the active deployment (ID ending in 44Pme8wCA)
  • Set Who has access = "Anyone" (required for public reserve widgets)
  • Set Execute as = Me (or the service account owning the sheets)
  • Deploy and verify HTTP 200 response

For the 404 worship endpoint:

  • Identify the current active deployment from script.google.com
  • Create a new deployment from the current project version
  • Update the worship event page to point to the new deployment ID
  • Test endpoint before live sync

Verification via command line (before and after):

curl -I "https://script.google.com/macros/s/.../44Pme8wCA/exec"
# Expected: HTTP 403 before fix
# Expected: HTTP 200 after fix

curl -I "https://script.google.com/macros/s/.../AFsLWaO3/exec"
# Expected: HTTP 404 before redeploy
# Expected: HTTP 200 after redeploy

Event Page Endpoints: S3 and CloudFront Distribution

The 11 event pages are hosted as static HTML on S3 with embedded deposit endpoint URLs:

  • S3 bucket: s3://sailjada-public-events/
  • CloudFront distribution: d...cloudfront.net (caching 5 minutes for .html files)
  • Route53 DNS: sailjada.com and queenofsandiego.com ALIAS records point to CloudFront

Event pages stored in S3:

s3://sailjada-public-events/reserve-page-template.html
s3://sailjada-public-events/events/[event-slug]/index.html
s3://sailjada-public-events/events/worship/index.html
(10 additional event pages)

Each contains hardcoded endpoint URLs in JavaScript:

<script>
  const DEPOSIT_ENDPOINT = "https://script.google.com/macros/s/.../44Pme8wCA/exec";
  // Reserve button click handler calls fetch(DEPOSIT_ENDPOINT, {method: 'POST', ...})
</script>

Once the Apps Script endpoints are restored to HTTP 200, the S3 pages require no changes. If endpoints are redeployed with new IDs, we perform a dry-run