Work / Chitragupt / Wiki / Decisions
2026-10-23-app-check-callables-only
Decisioncanonicalverified 2026-10-23
DECISION.2026-10-23.APP-CHECK-CALLABLES-ONLYApp 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— defaultenforceAppCheck: true;APP_CHECK_ENFORCEMENT_DISABLED=truebypasses for emulator and CI.firebase/firestore.rules,firebase/storage.rules— nohasAppCheck.- Firestore and Storage enforcement is the Enforce switch in the Firebase console.
- Still true from the original:
mintAppCheckTokenwith origin allow-list and per-IP rate limit;APP_CHECK_APP_IDenv needed in production.
Status
Active. Replaces 2026-06-28-phase-7a-app-check-enforcement.
Sources
apps/functions/src/_lib/callable.ts,auth/email-otp.ts,waitlist/waitlist.ts,marketplace/engagement.ts,grievance/file.ts- 2026-10-05-app-check-is-not-a-rules-check