Skip to content

Work / Chitragupt / Wiki / Decisions

2026-10-23-app-check-callables-only

Decisioncanonicalverified 2026-10-23

DECISION.2026-10-23.APP-CHECK-CALLABLES-ONLY

App Check is enforced on callables, not in security rules

Decision

onZodCall enforces App Check by default. Public callables opt out with enforceAppCheck: false: requestEmailOtp, verifyEmailOtp, joinWaitlist and listCaPublicReviews. fileGrievance is no longer public; it requires a signed-in user and App Check. No security rule reads App Check: hasAppCheck() is deleted from both rule files. The web client still gets tokens from the mintAppCheckToken custom provider.

Why

A rule cannot see the App Check token, so the planned rules-side check rejected every real caller and only passed in the emulator (2026-10-05-app-check-is-not-a-rules-check). Grievances moved behind sign-in in 2026-10-05-grievances-are-filed-signed-in. Signed-out CA browsing has no Firebase identity to bind a token to.

Impact

  • apps/functions/src/_lib/callable.ts — default enforceAppCheck: true; APP_CHECK_ENFORCEMENT_DISABLED=true bypasses for emulator and CI.
  • firebase/firestore.rules, firebase/storage.rules — no hasAppCheck.
  • Firestore and Storage enforcement is the Enforce switch in the Firebase console.
  • Still true from the original: mintAppCheckToken with origin allow-list and per-IP rate limit; APP_CHECK_APP_ID env needed in production.

Status

Active. Replaces 2026-06-28-phase-7a-app-check-enforcement.

Sources