Skip to content

One user in many farms: membership table + account switcher #539

Description

@mforce

Follow-up to epic #530 (Phase 1.6 — Multi-farm tenancy). Deliberately out of scope for that epic.

What #530 ships instead

Email is unique within a farm (#532). A person who works for two farms has two separate user rows and logs in twice, entering a different farm code each time. There is no switcher.

What this issue would add

One human, one session, many farms.

  • An AccountMembership join table: user ↔ account ↔ roles. Today ApplicationUser.AccountId is a single scalar column (src/Cluckwork.Infrastructure/Identity/ApplicationUser.cs:6-8) and the JWT's account_id is a straight passthrough of it (JwtTokenService.cs:36) — nothing ever chooses an account.
  • Account selection at login, or a token-exchange endpoint that swaps account_id without re-authenticating.
  • An account switcher in the SPA, which currently never decodes account_id at all (web/src/auth/claims.ts).

Why it is not cheap

Role assignments would move off AspNetUserRoles, which has no account column — roles are global singleton rows shared by every account (AspNetRoles, unique on NormalizedName, no AccountId). Membership roles would have to live in the new table instead, and every IsInRole path re-derived from it.

Three security mechanisms assume one user means one account and each needs re-examining per membership rather than per user:

Plus: what a switch does to an in-flight idempotency key, and whether audit rows record the human or the membership.

Worth revisiting when

A real customer has staff shared across farms, or an agronomist/consultant persona appears. Until then the two-logins answer is honest and costs nothing to reverse — the membership table can be added later without undoing #532, since a composite username is still a valid membership identity.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions