How a user wears one hat of many, switches to the hats that hat is allowed to assume, sees only the organizations that hat can reach, and acts either as a staff member beneath it or for a client on their behalf — plus the redesigned identity dropdown that makes it dynamic and DB-backed. Model locked 7/6/26.
Everything below was confirmed with Shattique on 7/6/26. These are the governing rules; the rest of the doc details how they are built. This same list is mirrored in the site standards doc.
is_primary org flag.pure_identity_hats (18 hats, 8 orgs today).is_primary breaks same-level ties.The canonical 7-level ladder (from the org-hierarchy doc). MLS sits above Association. Levels 0–3 are cross-org; level 4 is bound to one brokerage; levels 5–6 have no hats and no dropdown.
Example: a Designated Broker at Acquisto wears an Agent hat the org row is locked to Acquisto, and accessible hats show only roles reachable inside Acquisto. A PURE superadmin gets the org picker plus All orgs to search every user in the system.
There is no separate Clients tab. Client & Vendor already exist as level-5 rows in pure_hats, so they sit at the bottom of the same ROLE column when reachable. One consistent mental model — pick a role pick a person — where the kind of role decides the verb.
Borrow another staff member's hat / authority. Downward-only, org-scoped, targets levels 0–4. Button reads Act as; the pill says Viewing as Agent X.
Borrow a level-5 identity's context to do client-side work — property search, favorites, saved searches, portal actions — with the client's capabilities, not staff powers. Button reads Act for; the pill says Acting for Client Y; audited as "Agent X acting for Client Y."
Reach scales with level: an agent reaches only their own clients (linked through a deal); a broker/brokerage admin reaches any client on the brokerage's deals; a site admin (All orgs) reaches any client. The contextual "Act for this client" button on a client/deal record opens the same flow pre-targeted — the primary entry in practice.
One catalog table, one relationship table, the existing assignment table, and the existing deal/party junctions for client reach — all admin-editable.
| Table | Shape & purpose |
|---|---|
pure_orgs new | id, name, level ('poppy'|'pure'|'mls'|'association'|'brokerage'), parent_id — the org tree for levels 0–4. Level 5/6 are not rows here (no parent org). |
pure_hats (catalog) new | id, label, level int, rank int — the staff hat types + level number that drives "highest" and scope. |
pure_identity_hats exists | user_id, hat_id, org_id, is_primary — who holds which hat in which org. 18 rows today; add FKs to the two catalogs. |
pure_hat_relationships new | from_hat, can_wear_hat, org_scope ('own'|'descendants'|'all') — the delegation graph. "A Designated Broker may wear Agent / ISA / TC within its own org." The "hats relationship management" surface. |
| deal / party junctions exists | client deal (agent · brokerage). This is what makes act-for reach relationship-scoped — no parent_org on a client; reach = the junction rows that link a client to me or my org. |
select * from pure_identity_hats where user_id = me. No staff hat no dropdown (rule 1).level (highest authority); is_primary breaks ties (rule 8).can_wear_hat where from_hat = worn, ∩ selected org, strictly lower rank — rule 4) plus reachable level-5 rows (Client · Vendor) appended at the bottom.pure_identity_hats where org = selected and hat = selected role newest 10; search extends via DB over the whole eligible set. Action verb = Act as.The two-chip context row up top, then the scoped columns. The ROLE column carries staff hats and, at the bottom, the reachable Client/Vendor entries — no separate tab. Everything below is live from the DB.
L4 hat org locked to Acquisto. An MLS/Association/PURE hat unlocks the org picker + All orgs.
Staff hats the worn hat may assume (strictly lower rank, pure_hat_relationships) + reachable level-5 rows below the divider.
No role chosen = just operate as your worn hat.
Selecting Client or Vendor fills the right column with your reachable people (for an agent, the clients on their own deals) and the button reads Act for instead of Act as. The contextual "Act for this client" button on a client/deal record opens this same flow pre-targeted.
Phased, additive, reversible — and it dovetails with the Auth Window (RLS makes the scope a real boundary, not just a UI filter).
| # | Phase | Owner |
|---|---|---|
| 1 | Catalog + relationships. Create pure_orgs, pure_hats, pure_hat_relationships; add FKs to pure_identity_hats; seed the hats, the 7-level orgs, and the starter delegation graph. | Design Code |
| 2 | Read APIs. my_hats(), accessible_hats(worn,org), org_scope(worn), users_for(org,hat,search,limit), clients_for(me,search,limit), hat_counts(org). Read-only, PostgREST-friendly. | Code |
| 3 | Rebuild the dropdown — two-chip context row, locked-org for L4, unified ROLE column (staff hats + reachable Client/Vendor), DB search, staff-only render gate. Falls back to current behavior if APIs absent. | Design |
| 4 | Hat-relationship admin surface in Admin Center to manage pure_hat_relationships — who may wear whom, per scope. | Design |
| 5 | Server-side Act-As / Act-For. Gated, audited RPCs enforcing rank + scope for both modes — ties into Auth Window AW-4/AW-7 so impersonation holds under RLS. | Code |
| 6 | Backfill. Assign every L4 user to their brokerage; give real users their true hats; wire client reach off the deal/party junctions. | Mike Design |
Phases 1–4 are additive UI/data work, safe to build now. Phase 5 (server-enforced Act-As/Act-For) lands with the Auth Window RLS so impersonation is a real, audited boundary — not before, or it's cosmetic and bypassable.
PURE MLS Technologies · Hats, Orgs & Act-As — Model + Redesign Plan · model locked with Shattique 7/6/26 · prepared by Lane A