Skip to content

An admin cannot resolve an account id to a person #123

Description

@davidtaing

Two places on the admin surface ask a reviewer to make a judgement about an account, and neither can show them who the account is. Both landed in #122.

Assigning an owner. docs/spec/profile-and-credentials.md:75 is deliberate that the override is "a human check rather than a mechanism" — an admin decides, and no automated email match is wanted. But the check itself is "does the claimer's verified account email equal practitioner_contacts.contact_email", and the panel can only show one side of it: the contact address is rendered, and the input takes an account uuid. The admin is being asked to compare an address against an opaque identifier, so in practice the comparison happens in the Supabase dashboard in another tab, or it does not happen. The consequence of getting it wrong is real — the profile is handed over, every credential's verified is cleared, and A → B is refused by the guard, so the repair is unassign-then-reassign.

Naming who performed a check. practitioner_credentials.verified_by is an account id. The queue currently renders your own check as Checked by <you>, anybody else's as another Bluehex admin, and a null one as with no admin recorded — which is reachable today, since every seeded verified row has it null. "Another Bluehex admin" is the honest thing to say when the id cannot be resolved, and it is a poor substitute for a name on the surface whose whole subject is who vouched for what.

Why it is a migration rather than a query

auth is not an exposed schema, so PostgREST cannot reach auth.users at all, and public.admins carries no grant to bluehex_admin. There is nothing to select.

The likely shape is one narrow security definer function returning an email for an account id, executable by bluehex_admin alone — the same idiom as my_profile() in 20260822050002_profile_own_reads.sql, and subject to the same rule that the predicate is the whole control. Both callers above are served by it. Worth deciding at the same time whether it takes one id or a set, since the queue would call it once per verified credential otherwise.

Not to be built

An automated email match on assignment. The spec refuses it on purpose — that override is exactly where social engineering comes back, and a mechanism there would launder a human decision into an automatic one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: dbPostgres schema, migrations, RLS, queriesenhancementNew feature or requesthitlNeeds a human (decision/design/review)size: SAn evening for someone new to this codebase

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions