The app kit
Your own Cloud Functions in functions/src/custom/ use Arc CMS's accounts, claims and sign-in through one import, functions/src/app-kit/index.ts. What it exports is supported: it keeps its meaning across Arc CMS updates, and a test fails if it changes without this page.
import { createAppAccount, issueSignInToken, mergeAppClaims } from '../app-kit/index.js';
Everything else in functions/src is core's to change. You may read it to learn how something works, but import from the kit, and ask for a missing export in Arc CMS rather than reaching past it.
Exports
| Export | What it does | Guide |
|---|---|---|
createAppAccount() | Creates a sign-in account and its users record for a person with no email and no phone. Takes { displayName, claims?, uid?, selfService? }, returns { uid, userDocId }. The account is locked unless selfService is true. | App accounts |
deleteAppAccount() | Deletes a person's account by their Auth uid; Arc CMS's account deletion does the rest and announces user.deleted. | App accounts |
restoreAppSignIn() | Gives an app account its sign-in back after the browser deleted it: the same uid, the record's name, Arc CMS's claims and the ones you pass, in one write. Safe to repeat. | App accounts |
APP_ACCOUNT | 'app': the by value of a record createAppAccount() made. | App accounts |
mergeAppClaims() | Merges your own claims into any account: refuses arccms_ and Firebase's reserved names and anything over Firebase's 1000-byte limit, never replaces what is there, removes a claim with null. | App accounts |
isArcAdmin() | Whether an ID token (request.auth?.token) or an account's claims make the holder an Arc CMS admin, for a callable only admins may use. | App accounts |
revokeSessions() | Signs a person out everywhere: their sessions end at the next token refresh, within the hour. | App accounts |
issueSignInToken() | A custom token for a uid, which the browser exchanges with signInWithCustomToken. When Google Cloud cannot sign tokens yet, it says so and alerts the admins. | App accounts |
signedInByApp() | Whether a callable's caller signed in with your sign-in token (signedInByApp(request)), never with a sign-in linked in the browser. The callable twin of the rules helper of the same name. | App accounts |
createPinStore() | A place for your app's PINs, apart from Arc CMS's phone PINs: createPinStore(namespace, { maxAttempts, strength }) gives set, check, has, clearLock and remove. | PINs for your app |
createPhonePinCheck() | Checks the signed-in person's phone sign-in PIN at a gate inside your app, such as a parent area, counting wrong tries apart from sign-in: createPhonePinCheck(namespace, { maxAttempts }) gives has, check and clearLock. Never for signing in. | PINs for your app |
APP_PINS | 'app_pins': the collection every app PIN is kept in, closed to the browser. | PINs for your app |
isValidPin() | Whether a value is a PIN at all: exactly 6 digits. | PINs for your app |
isWeakPin() | Whether a 6-digit PIN is too easy to guess (one digit repeated, a straight run, a common pattern). | PINs for your app |
pinTooEasy() | Whether a new PIN is refused under the app's strength: isWeakPin() when it is strict, never when it is simple. pinTooEasy(pin, strength?); leave the strength out for the app's. | PINs for your app |
signInStrength() | The password and PIN strength the app chose in src/custom/sign-in.ts: 'strict' or 'simple'. | Set up sign-in |
consumeRateLimit() | Counts one use of a key in a time window and refuses with resource-exhausted once the limit is reached: consumeRateLimit(key, max, windowMs, message, reason?). The refusal's details carry reason (default too-many-attempts) and retryAfter, the seconds until the window reopens. | PINs for your app |
hashedKey() | A rate-limit key you choose, such as a device id, hashed and kept apart from Arc CMS's keys: hashedKey('kiosk-device', deviceId). | PINs for your app |
callerKey() | A rate-limit key for the caller's address, hashed. { trustedProxies: 1 } for a function reached through a Hosting rewrite. | PINs for your app |
Errors a person can act on are HttpsErrors with code invalid-argument or not-found, so a callable can let them through as they are.