User_earthranger_ids
Per-herd EarthRanger subject ids for users whose herds use different EarthRanger instances
| Column Name | Data Type | Constraints |
|---|---|---|
| user_id | uuid | NOT NULL, FK -> users (cascade), PK part |
| herd_id | bigint | NOT NULL, FK -> herds (cascade), PK part |
| earthranger_id | text | NOT NULL, non-blank |
| inserted_at | timestamp with time zone | DEFAULT timezone('utc', now()) NOT NULL |
| updated_at | timestamp with time zone | DEFAULT timezone('utc', now()) NOT NULL, maintained by trigger |
One row per (user_id, herd_id). users.earthranger_id remains as the legacy single id and is the fallback when no row exists for a herd; the migration seeded one row per active membership from it. Resolve with public.user_earthranger_id(user_id, herd_id). It returns the per-herd row when one exists, otherwise the legacy column, and null when the caller is not the user, a platform superadmin, or a holder of herds.read in that herd. Merging two accounts moves the source's rows to the target for herds the target has no row in.
Security Policies (RLS)
RLS enabled. Herd scope: Herd from user_earthranger_ids.herd_id.
| Operation | has_herd_ability ability key | Other paths |
|---|---|---|
| SELECT | herds.read | Own rows (user_id = auth.uid()) |
| INSERT / UPDATE / DELETE | users_roles_per_herd.write | Own rows, if the user is an active member of that herd |
Platform superadmin: FOR ALL bypass.