Why this exists
“When did this customer last sign in?” and “why can’t this person log in?” are among the most common support questions there are, and the usual answers are both bad: give a support engineer a Firebase console seat over the whole project, or make an engineer stop and look it up. Auth capabilities make the question answerable in Slack, scoped to reads, and recorded in the audit log — while account changes still stop for a human.Read-only enforcement
GCP IAM
The runner’s runtime service account receives
roles/firebaseauth.viewer.
GCP rejects write operations at the API boundary.Runner query surface
Built-in Auth queries call read methods only. Mutations are a separate,
approval-gated family that is never implied by enabling reads.
What is deliberately not here
Some Admin SDK methods are absent at every grant level, not merely gated:
Password reset and sign-in links are available, in the mutation family, for
the reason given below.
1. Bind the runtime identity
Grant the runner’s service accountroles/firebaseauth.viewer on the Firebase
project. Add roles/firebaseauth.admin only if you intend to enable mutations
with ambient credentials.
2. Enable Auth queries
polycore.json
integrations.firebase block resolves the project id once and every
service under it shares it — from FIRESTORE_PROJECT_ID, GOOGLE_CLOUD_PROJECT,
or GCLOUD_PROJECT, or from a variable you name with projectIdEnv. Auth is an
independent grant: a runner can serve Firestore reads without ever exposing the
auth directory, and the reverse.
Available capabilities
read
Reads one account by uid: profile, verification and disabled state, custom
claims, linked providers, and creation / last sign-in / last refresh times.
read
Reads one account by exact email address.
read
Reads one account by exact phone number in E.164 form.
read
Reads one account by its identifier at a federated provider, e.g. a Google
account id.
read
Resolves up to 100 identifiers of mixed kinds — uid, email, phone, provider
uid — in one call, reporting which matched nothing.
read
Pages the directory in creation order for enumeration and audit.
read
Lists configured SAML or OIDC providers with their endpoints and enabled
state.
read
Reads one SAML or OIDC provider configuration by id.
There is no search
Firebase Auth supports exact lookups and a full directory page-through. There is no substring, prefix, or fuzzy match on email or name, and no amount of capability design can add one. Each capability says so in its own description, so a caller without an exact identifier asks for one instead of paging the whole directory hoping to spot a match.Not-found is an answer
Every exact lookup returnsnull rather than raising when nothing matches — the
same shape firestore.get uses. A raised error reads like a failed call worth
retrying or routing around; a null is the answer to the question.
No multi-tenancy
Identity Platform tenants are not supported, deliberately. Every capability acts on the project’s own directory. An optionaltenantId used to sit on each capability. It was a parameter models
filled in unprompted — one sent "/" — and on a project without Identity
Platform any value fails inside the Admin SDK, turning a working lookup into an
opaque Error while parsing response data. It could only ever break a call that
would otherwise have worked, so it was removed along with the tenant listing
capabilities. If a deployment ever genuinely needs tenants, the scope belongs in
polycore.json where it is reviewed once — never in a per-call argument the
model chooses.
Optional: generic mutations
Mutations are off until you grant them explicitly. Enabling reads never implies them, and upgrading the runner package never adds them.polycore.json
"ambient"— writes use Application Default Credentials. Choose this when the runtime service account already administers Auth.{ "keyEnv": "…" }— writes use a separate write-capable service account read from that environment variable, so the runtime identity staysroles/firebaseauth.viewer. Only the variable name is committed.
write-hazard: the control plane holds the request until a
human approves that exact call with those exact arguments.
write
Creates one account. Fails if the email or phone already belongs to another
account, so it can never silently take over an existing identity.
write
Changes email, phone, password, profile, verified flag, or disabled state.
Only the properties passed change.
write
Permanently deletes one account. Removes the identity only — data keyed by
that uid is untouched, and the uid is unrecoverable.
write
Deletes up to 50 accounts by explicit uid. Every uid appears in the approval.
write
Replaces the user’s custom claims — the token fields most apps use for roles
and entitlements. Replaces rather than merges.
write
Signs the user out of all devices. The standard response to a compromised
account, and the way to make a disable or claims change take effect at once.
write
Generates a password-reset link for an email address.
write
Generates an email-verification link for a registered address.
write
Generates a passwordless sign-in link.

