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:
- Navigate to
script.google.com - Open the project with ID
1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5 - Click Deploy → Manage deployments
- 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
- 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