Skip to content

Profile Inspector โ€” Firestore & Auth Diagnostic Tool โ€‹

Last Updated: 2026-03-18

A unified inspection tool that queries Firebase Auth, users, adminProfiles, and merchantProfiles for a given UID and presents them side by side with automatic consistency checks.

Why this exists: Admin users have data spread across users/{uid} and adminProfiles/{uid} (same UID, different collections). Fields like displayName, phone, and updatedAt can drift out of sync. This tool makes mismatches immediately visible.


Quick Start โ€‹

bash
# Full inspection โ€” Auth + users + adminProfiles + merchantProfiles
./tooling/scripts/inspect-profile.sh <USER_UID>

# Compare shared fields between users and adminProfiles
./tooling/scripts/inspect-profile.sh <USER_UID> --diff

# Raw JSON (pipe to jq, save to file, etc.)
./tooling/scripts/inspect-profile.sh <USER_UID> --json

# Inspect only one source
./tooling/scripts/inspect-profile.sh <USER_UID> --collection users
./tooling/scripts/inspect-profile.sh <USER_UID> --collection adminProfiles
./tooling/scripts/inspect-profile.sh <USER_UID> --collection auth

# Target a different project
./tooling/scripts/inspect-profile.sh <USER_UID> --project lantern-app-prod

Prerequisites โ€‹

  • Node.js 22+
  • firebase-admin installed (available in the repo's root node_modules)
  • Application Default Credentials for the target project, or GOOGLE_CLOUD_PROJECT set in .env.local

What It Shows โ€‹

Summary Header โ€‹

A quick at-a-glance view:

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘  PROFILE INSPECTOR โ€” aR7ivxIk48Wi...            โ•‘
โ•‘  Project: lantern-app-dev                        โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

  Summary:
  UID:              aR7ivxIk48Wijw1nXBs8C9KyfhB2
  Role:             admin
  Auth record:      โœ“
  users doc:        โœ“
  adminProfiles:    โœ“
  merchantProfiles: โ€”

Automatic Consistency Warnings โ€‹

The script checks for common mismatches and flags them:

CheckExample Warning
Admin role but no adminProfiles docUser has admin role but NO adminProfiles document
adminProfiles exists but role โ‰  adminUser has adminProfiles document but role is "user", not admin
Merchant role but no merchantProfiles docUser has merchant role but NO merchantProfiles document
Email mismatch (Auth vs Firestore)Email mismatch: Auth=a@b.com, Firestore=x@y.com
displayName mismatch (Auth vs users)displayName mismatch: Auth="Foo", users="Bar"
displayName mismatch (users vs adminProfiles)displayName mismatch: users="Foo", adminProfiles="Bar"

Collection Sections โ€‹

Each source is printed with all fields, ordered alphabetically. Long encrypted/sensitive values are truncated with length indicators:

  • [encrypted] โ€” Client-side encrypted fields (e.g., encryptedBirthDate, encryptedSeed)
  • [sensitive] โ€” Key material or hashes (e.g., salt, phoneSalt, authProofHash)

Diff Mode (--diff) โ€‹

Compares the four shared fields between users and adminProfiles:

  • displayName
  • phone
  • githubUsername
  • updatedAt

Flags mismatches with โš  and shows both values. Also lists fields unique to each collection.


Options Reference โ€‹

FlagDescription
--jsonOutput raw JSON instead of formatted table. Timestamps are ISO 8601.
--diffShow field-by-field comparison of users vs adminProfiles.
--collection <name>Only query one source: users, adminProfiles, merchantProfiles, or auth.
--project <id>Override Firebase project (default: lantern-app-dev).

Collections Compared โ€‹

users/{uid} โ€‹

The main user profile document. Contains public fields (lanternName, interests, mood), encrypted personal data, encryption key material, auth method fields, role/ban state, and timestamps.

adminProfiles/{uid} โ€‹

Supplementary document for admin users. Contains displayName (real name), phone (emergency contact), emergencyContact, notes, githubUsername, and admin password fields. Same UID as users.

merchantProfiles/{uid} โ€‹

Supplementary document for merchant users. Created by Cloud Functions only. Read by merchants (own doc) and admins (all docs).

Firebase Auth Record โ€‹

The authentication record: email, phone, providers, custom claims (role), disabled state, and login timestamps.


Common Workflows โ€‹

"Is this admin fully set up?" โ€‹

bash
./tooling/scripts/inspect-profile.sh <UID>

Check for:

  • Auth record: โœ“ and customClaims: {"role":"admin"}
  • users doc: โœ“ with role: admin
  • adminProfiles: โœ“ with displayName populated
  • No consistency warnings

"Why is displayName wrong in the admin portal?" โ€‹

bash
./tooling/scripts/inspect-profile.sh <UID> --diff

The admin portal reads from adminProfiles.displayName, while the main app may show users.displayName or Auth.displayName. The diff shows which one is stale.

"Quickly check encryption state" โ€‹

bash
./tooling/scripts/inspect-profile.sh <UID> --collection users

Look for salt or phoneSalt (which auth method), encryptionCanary, encryptedSeed, and recoveryBackupBlob.

"Export profile data for debugging" โ€‹

bash
./tooling/scripts/inspect-profile.sh <UID> --json > /tmp/profile-debug.json

See Also โ€‹

Built with VitePress