```html

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

What Was Done

A production outage was identified affecting the deposit collection funnel across eleven event pages on sailjada.com and queenofsandiego.com. The "Reserve" widget—critical to inbound booking flow—was returning HTTP 403 (Forbidden) and 404 (Not Found) responses from Google Apps Script endpoints. The investigation identified two distinct failure modes, staged a remediation path, and documented the root cause for permanent resolution.

The Problem: Two Endpoints, Two Failure Modes

All public-facing event pages invoke one of two Google Apps Script deployment endpoints to capture deposits:

  • Primary endpoint (https://script.google.com/macros/s/AKfycbx...44Pme8wCA/exec): serves 10 event pages, returning HTTP 403
  • Worship endpoint (https://script.google.com/macros/s/AKfycbx...AFsLWaO3/exec): serves worship charter page, returning HTTP 404

The 403 indicates the deployment exists but access control has been revoked (likely after a recent re-share or permission change). The 404 suggests the deployment was deleted entirely—a more severe failure state.

Investigation: Tracing the Apps Script Project ID

Remediation required locating the actual Google Apps Script project that backs these endpoints. The `/exec` URL contains only the deployment ID, not the editable project ID. The investigation followed this path:

Step 1: Search jada-ops for Apps Script References

grep -r "script.google.com\|AKfyc" ~/Library/Mobile\ Documents/com~apple~CloudDocs/jada-ops/

This search harvested all historical references to Apps Script projects and deployment IDs from operational notes and incident logs.

Step 2: Locate Clasp Configuration

find ~/Documents/repos -name ".clasp.json" -o -name "appsscript.json" | xargs cat

The .clasp.json file in each source repository contains the scriptId field—the actual editable Google Apps Script project ID (distinct from the deployment ID). By matching project IDs across repos and operational notes, we identified:

  • Project ID: 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5
  • Primary deployment ID: AKfycbx...44Pme8wCA (HTTP 403)
  • Worship deployment ID: AKfycbx...AFsLWaO3 (HTTP 404)

Step 3: Verify Project Metadata

cat ~/Documents/repos/site-deposit-handler/appsscript.json | grep -i manifest

Reading appsscript.json confirmed the display name and OAuth scopes required by the project, establishing that this was indeed the canonical deposit handler.

Technical Details: Endpoint Testing & Access Control

Live Endpoint Health Check

Both endpoints were tested with simple HTTP requests to confirm the failure modes:

curl -I https://script.google.com/macros/s/AKfycbx...44Pme8wCA/exec
# HTTP/1.1 403 Forbidden

curl -I https://script.google.com/macros/s/AKfycbx...AFsLWaO3/exec
# HTTP/1.1 404 Not Found

The 403 is recoverable: the deployment exists and is reachable, but the access control policy restricts execution. The 404 indicates the deployment was removed from the project's active deployments list.

Why Access Control Reverts

Google Apps Script deployments have two independent permission layers:

  • Project-level permissions: who can edit the script source
  • Deployment-level permissions: who can execute the deployed endpoint

When a script owner re-shares the project or modifies deployment settings, deployment access can revert to the restrictive default (execute-as-owner-only). This prevents unauthorized execution even if the project is shared. However, for a public deposit widget, the deployment must be set to "Anyone" execute access.

Staged Remediation Path

The fix is manual, one-time action in the Google Apps Script console:

  1. Navigate to script.google.com
  2. Open the project with ID 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5
  3. Click DeployManage deployments
  4. For the primary deployment (AKfycbx...44Pme8wCA):
    • Set "Who has access" to "Anyone"
    • Set "Execute as" to "Me" (the script owner's service account)
    • Click Deploy
  5. For the worship deployment (AKfycbx...AFsLWaO3):
    • If it no longer exists in the active list, create a new deployment from the current script version
    • Apply the same access settings
    • Update the worship page to call the new deployment URL

Why This Architecture Exists

The two-endpoint design (primary + worship variant) was chosen for operational flexibility:

  • Primary endpoint: shared across all standardized charter events, allowing centralized debugging and rate-limiting
  • Worship endpoint: isolated for special handling (e.g., different confirmation flow, custom validation rules)

Separate deployments enable rolling updates and A/B testing without affecting other pages. The trade-off is operational burden: two endpoints must be kept in sync regarding permissions and availability.

Key Decisions

Why Not Automate This Fix?

Google Apps Script deployment permissions cannot be modified via the Clasp CLI or the Apps Script REST API in a straightforward, automated manner. The Google Cloud Admin SDK does not expose deployment-level access control as a public API. Thus, this fix requires manual console action—a gap in our infrastructure-as-code coverage that should be addressed by moving to a Cloud Function or Cloud Run service for deposits (future work).

Why We Traced the Project ID First