<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FUser_%26_Skills</id>
	<title>References/User &amp; Skills - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://ohcnwiki.tellmey.fyi/index.php?action=history&amp;feed=atom&amp;title=References%2FUser_%26_Skills"/>
	<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/User_%26_Skills&amp;action=history"/>
	<updated>2026-07-06T05:22:13Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.4</generator>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/User_%26_Skills&amp;diff=428&amp;oldid=prev</id>
		<title>Admin: Automated edit (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/User_%26_Skills&amp;diff=428&amp;oldid=prev"/>
		<updated>2026-07-06T04:07:46Z</updated>

		<summary type="html">&lt;p&gt;Automated edit (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:37, 6 July 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 396:&lt;/td&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 396:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;is_service_account&amp;lt;/code&amp;gt; distinguishes machine/integration accounts from human users.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;is_service_account&amp;lt;/code&amp;gt; distinguishes machine/integration accounts from human users.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Write through &amp;lt;code&amp;gt;UserCreateSpec&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt;; read through &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; (list), &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; (detail), &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt; (self), and &amp;lt;code&amp;gt;PublicUserReadSpec&amp;lt;/code&amp;gt; (public). Picture URLs, MFA status, roles, flags, and nested org/creator objects are all computed server-side.&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Write through &amp;lt;code&amp;gt;UserCreateSpec&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt;; read through &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; (list), &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; (detail), &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt; (self), and &amp;lt;code&amp;gt;PublicUserReadSpec&amp;lt;/code&amp;gt; (public). Picture URLs, MFA status, roles, flags, and nested org/creator objects are all computed server-side.&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Navbox access governance}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Related}}&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td colspan=&quot;2&quot; class=&quot;diff-empty diff-side-deleted&quot;&gt;&lt;/td&gt;
  &lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;
  &lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Wiki: ohcnwiki.tellmey.fyi&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://ohcnwiki.tellmey.fyi/index.php?title=References/User_%26_Skills&amp;diff=132&amp;oldid=prev</id>
		<title>Admin: OHC identity seed</title>
		<link rel="alternate" type="text/html" href="https://ohcnwiki.tellmey.fyi/index.php?title=References/User_%26_Skills&amp;diff=132&amp;oldid=prev"/>
		<updated>2026-07-04T22:43:59Z</updated>

		<summary type="html">&lt;p&gt;OHC identity seed&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Doc header&lt;br /&gt;
|type=reference&lt;br /&gt;
|domain=access-governance&lt;br /&gt;
|title=User &amp;amp; Skills&lt;br /&gt;
|order=2&lt;br /&gt;
|introduced=3.0&lt;br /&gt;
|model=User&amp;amp;Skills&lt;br /&gt;
|concept=Concepts/Patient&lt;br /&gt;
|reference=References/Base models &amp;amp;amp; conventions&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; is a Care account — authentication, profile, clinician credentials, and notification/MFA data. The Django model is the storage layer. The Pydantic resource specs in &amp;lt;code&amp;gt;care/emr/resources/user/&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;care/emr/resources/mfa/&amp;lt;/code&amp;gt; are the API layer: they define enums, validation, the shape of the opaque &amp;lt;code&amp;gt;JSONField&amp;lt;/code&amp;gt;s, and the separate request/response schemas you write to and read from.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Source:&amp;#039;&amp;#039;&amp;#039; [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/users/models.py &amp;lt;code&amp;gt;care/users/models.py&amp;lt;/code&amp;gt;], [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/facility/models/patient.py &amp;lt;code&amp;gt;care/facility/models/patient.py&amp;lt;/code&amp;gt;], [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/user/spec.py &amp;lt;code&amp;gt;care/emr/resources/user/spec.py&amp;lt;/code&amp;gt;], [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/mfa/spec.py &amp;lt;code&amp;gt;care/emr/resources/mfa/spec.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Models ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Model&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt;&lt;br /&gt;
| Care account: authentication, profile, clinician credentials, and notification/MFA data&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Skill&amp;lt;/code&amp;gt;&lt;br /&gt;
| Instance-wide skill/competency definition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserSkill&amp;lt;/code&amp;gt;&lt;br /&gt;
| Through model linking a &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; to a &amp;lt;code&amp;gt;Skill&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserFlag&amp;lt;/code&amp;gt;&lt;br /&gt;
| Feature flag scoped to a single &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PlugConfig&amp;lt;/code&amp;gt;&lt;br /&gt;
| Slug-keyed JSON configuration for installed plugs&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MobileOTP&amp;lt;/code&amp;gt;&lt;br /&gt;
| One-time password issued against a phone number&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base class determines which audit fields each model carries:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; extends Django&amp;#039;s &amp;lt;code&amp;gt;AbstractUser&amp;lt;/code&amp;gt;, adding its own &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt; and a soft-delete &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt; flag. It is not an &amp;lt;code&amp;gt;EMRBaseModel&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Skill&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UserSkill&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;MobileOTP&amp;lt;/code&amp;gt; extend [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt;]] (&amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_date&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;modified_date&amp;lt;/code&amp;gt;, soft-delete via &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;UserFlag&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;BaseFlag&amp;lt;/code&amp;gt;, a &amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt; subclass that adds a &amp;lt;code&amp;gt;flag&amp;lt;/code&amp;gt; field plus a cache-invalidating &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;PlugConfig&amp;lt;/code&amp;gt; extends plain &amp;lt;code&amp;gt;django.db.models.Model&amp;lt;/code&amp;gt; — no audit or soft-delete fields.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; fields ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; inherits &amp;lt;code&amp;gt;password&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;first_name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;last_name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_staff&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_active&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_superuser&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;last_login&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;date_joined&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;AbstractUser&amp;lt;/code&amp;gt;. The fields below are Care additions or overrides. Queries run through &amp;lt;code&amp;gt;CustomUserManager&amp;lt;/code&amp;gt;, which drops &amp;lt;code&amp;gt;deleted=True&amp;lt;/code&amp;gt; rows by default; &amp;lt;code&amp;gt;get_entire_queryset()&amp;lt;/code&amp;gt; bypasses that filter.&lt;br /&gt;
&lt;br /&gt;
=== Identity &amp;amp;amp; profile ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=external_id|type=UUIDField|notes=Unique, indexed; stable public identifier. Surfaced as &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; in every read spec}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=username|type=CharField(150)|notes=Unique; model-validated by &amp;lt;code&amp;gt;UsernameValidator&amp;lt;/code&amp;gt;. On create, the API additionally enforces &amp;lt;code&amp;gt;^[a-zA-Z0-9_-]{3,}$&amp;lt;/code&amp;gt; and global uniqueness, including deleted users}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=user_type|type=CharField(100)|notes=Nullable; free-text role label (e.g. &amp;lt;code&amp;gt;administrator&amp;lt;/code&amp;gt;). No user spec exposes it — set internally or by &amp;lt;code&amp;gt;create_superuser&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=prefix|type=CharField(10)|notes=Name prefix (e.g. Dr.); spec caps length at 10. Optional in specs}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=suffix|type=CharField(50)|notes=Name suffix; spec caps length at 50. Optional in specs}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=gender|type=CharField(100)|notes=Nullable in DB. Write specs constrain it to &amp;lt;code&amp;gt;GenderChoices&amp;lt;/code&amp;gt; and require it; read specs return it as a plain string. See [[#genderchoices-values}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=old_gender|type=IntegerField|notes=Legacy &amp;lt;code&amp;gt;GENDER_CHOICES&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; Male, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; Female, &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; Non-binary); nullable. No user spec exposes it}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=date_of_birth|type=DateField|notes=Nullable. Read-only (nullable string) in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=profile_picture_url|type=CharField(500)|notes=Storage key, not a URL. Read specs return the resolved URL via &amp;lt;code&amp;gt;read_profile_picture_url()&amp;lt;/code&amp;gt;, not the raw key}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=created_by|type=FK → User (self, SET_NULL)|notes=Account creator; &amp;lt;code&amp;gt;related_name=&amp;amp;quot;users_created&amp;amp;quot;&amp;lt;/code&amp;gt;. Serialized in &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; as a cached nested &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; dict (nullable)}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=deleted|type=BooleanField|notes=Soft-delete flag (default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;); read-only in &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=verified|type=BooleanField|notes=Default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;; read-only in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Identity &amp;amp;amp; profile|name=is_service_account|type=BooleanField|notes=Default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;; marks machine/integration accounts. Settable on create, read in &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contact ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Contact|name=phone_number|type=CharField(14)|notes=Model: &amp;lt;code&amp;gt;mobile_or_landline_number_validator&amp;lt;/code&amp;gt;. Required in specs, capped at 14 chars; must be globally unique on create}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Contact|name=alt_phone_number|type=CharField(14)|notes=Nullable; model &amp;lt;code&amp;gt;mobile_validator&amp;lt;/code&amp;gt;. Read-only string in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Contact|name=video_connect_link|type=URLField|notes=Nullable; tele-consult link. No user spec exposes it}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Clinician credentials ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Clinician credentials|name=qualification|type=TextField|notes=Nullable. Read-only (nullable string) in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Clinician credentials|name=doctor_experience_commenced_on|type=DateField|notes=Nullable; experience is derived from this. Read-only (nullable string) in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Clinician credentials|name=doctor_medical_council_registration|type=CharField(255)|notes=Nullable; council registration number. Read-only (nullable string) in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Clinician credentials|name=weekly_working_hours|type=IntegerField|notes=Nullable; model-validated &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;168&amp;lt;/code&amp;gt;. Read-only (nullable string) in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Organization &amp;amp;amp; facility ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Organization &amp;amp;amp; facility|name=geo_organization|type=FK → emr.Organization (SET_NULL)|notes=Geographic/administrative org. Write specs accept a &amp;lt;code&amp;gt;UUID4&amp;lt;/code&amp;gt; and resolve it to an &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;org_type=&amp;amp;quot;govt&amp;amp;quot;&amp;lt;/code&amp;gt; (404 otherwise). Read in &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; as a nested &amp;lt;code&amp;gt;OrganizationReadSpec&amp;lt;/code&amp;gt; dict. Listed in &amp;lt;code&amp;gt;UserBaseSpec.__exclude__&amp;lt;/code&amp;gt;, so it never round-trips through the generic field copy}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Organization &amp;amp;amp; facility|name=home_facility|type=FK → facility.Facility (PROTECT)|notes=Primary facility. No user spec exposes it}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Organization &amp;amp;amp; facility|name=skills|type=ManyToManyField → Skill|notes=Through &amp;lt;code&amp;gt;UserSkill&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Organization &amp;amp;amp; facility|name=cached_role_orgs|type=JSONField|notes=Nullable; cached role/organization map. Lazily populated by &amp;lt;code&amp;gt;get_cached_role_orgs()&amp;lt;/code&amp;gt; and surfaced as &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt; in read specs. Platform-maintained — do not write directly}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Notifications, MFA &amp;amp;amp; preferences ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Notes&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=pf_endpoint|type=TextField|notes=Web-push endpoint; nullable. Read-only in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=pf_p256dh|type=TextField|notes=Web-push key; nullable. Read-only in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=pf_auth|type=TextField|notes=Web-push auth secret; nullable. Read-only in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=totp_secret|type=TextField|notes=Nullable; TOTP seed. Never serialized; written only via the MFA setup/verify flow}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=mfa_settings|type=JSONField|notes=Default &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;. Shape: &amp;lt;code&amp;gt;{ &amp;amp;quot;totp&amp;amp;quot;: { &amp;amp;quot;enabled&amp;amp;quot;: bool, ... } }&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;is_mfa_enabled()&amp;lt;/code&amp;gt; reads &amp;lt;code&amp;gt;mfa_settings[&amp;amp;quot;totp&amp;amp;quot;][&amp;amp;quot;enabled&amp;amp;quot;]&amp;lt;/code&amp;gt;; surfaced as the boolean &amp;lt;code&amp;gt;mfa_enabled&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;. Clients never write it directly}}&lt;br /&gt;
{{Field|model=User&amp;amp;Skills|section=Notifications, MFA &amp;amp;amp; preferences|name=preferences|type=JSONField|notes=Default &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;; open per-user UI/app preferences bag. Read-only &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;REQUIRED_FIELDS = [&amp;amp;quot;email&amp;amp;quot;]&amp;lt;/code&amp;gt;, and the model is managed by &amp;lt;code&amp;gt;CustomUserManager&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enum values ==&lt;br /&gt;
&lt;br /&gt;
=== GenderChoices values ===&lt;br /&gt;
&lt;br /&gt;
Bound to &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt; on every write spec (&amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UserCreateSpec&amp;lt;/code&amp;gt;). Defined in [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/patient/spec.py &amp;lt;code&amp;gt;care/emr/resources/patient/spec.py&amp;lt;/code&amp;gt;] and reused here; read specs return &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt; as a free string.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;male&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;female&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;non_binary&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;transgender&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;create_superuser()&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;gender=&amp;amp;quot;non_binary&amp;amp;quot;&amp;lt;/code&amp;gt;, which is a member of this enum. The model&amp;#039;s legacy integer &amp;lt;code&amp;gt;GENDER_CHOICES&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; Male, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; Female, &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; Non-binary) is separate and unused by the API.&lt;br /&gt;
&lt;br /&gt;
=== LoginMethod values ===&lt;br /&gt;
&lt;br /&gt;
Used by &amp;lt;code&amp;gt;MFALoginRequest.method&amp;lt;/code&amp;gt; in [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/mfa/spec.py &amp;lt;code&amp;gt;care/emr/resources/mfa/spec.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value&lt;br /&gt;
! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;totp&amp;lt;/code&amp;gt;&lt;br /&gt;
| Authenticator app one-time code&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;backup&amp;lt;/code&amp;gt;&lt;br /&gt;
| Single-use backup recovery code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Resource specs (API schema) ==&lt;br /&gt;
&lt;br /&gt;
Every user spec builds on &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt; ([&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;care/emr/resources/base.py&amp;lt;/code&amp;gt;]), which provides &amp;lt;code&amp;gt;serialize&amp;lt;/code&amp;gt; (DB → pydantic) and &amp;lt;code&amp;gt;de_serialize&amp;lt;/code&amp;gt; (pydantic → DB) plus the &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;perform_extra_deserialization&amp;lt;/code&amp;gt; hooks. &amp;lt;code&amp;gt;UserBaseSpec&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;__model__ = User&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;__exclude__ = [&amp;amp;quot;geo_organization&amp;amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Spec class&lt;br /&gt;
! Role&lt;br /&gt;
! Fields / behaviour&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserBaseSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| shared base&lt;br /&gt;
| &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;first_name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;last_name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;phone_number&amp;lt;/code&amp;gt; (max 14), &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt; (max 10, optional), &amp;lt;code&amp;gt;suffix&amp;lt;/code&amp;gt; (max 50, optional)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · update&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;GenderChoices&amp;lt;/code&amp;gt;, required), &amp;lt;code&amp;gt;phone_number&amp;lt;/code&amp;gt; (max 14), &amp;lt;code&amp;gt;geo_organization&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;UUID4&amp;lt;/code&amp;gt;, optional). De-serialize resolves &amp;lt;code&amp;gt;geo_organization&amp;lt;/code&amp;gt; to an &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;org_type=&amp;amp;quot;govt&amp;amp;quot;&amp;lt;/code&amp;gt; (404 if missing)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserCreateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · create&lt;br /&gt;
| Extends &amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;password&amp;lt;/code&amp;gt; (optional), &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_service_account&amp;lt;/code&amp;gt; (default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;role_orgs: list[UserRoleOrgCreateSpec]&amp;lt;/code&amp;gt;. Validates username pattern/uniqueness, phone uniqueness, email format/uniqueness, and password strength. De-serialize stashes &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt; on the instance and calls &amp;lt;code&amp;gt;set_password()&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserRoleOrgCreateSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| write · nested&lt;br /&gt;
| &amp;lt;code&amp;gt;organization: UUID4&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;role: UUID4&amp;lt;/code&amp;gt; — one role-in-organization assignment supplied at user creation&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · list/summary&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;last_login&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;profile_picture_url&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt; (string), &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mfa_enabled&amp;lt;/code&amp;gt; (default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;phone_number&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt; (default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;role_orgs: dict&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;@cacheable(use_base_manager=True)&amp;lt;/code&amp;gt; — cached, and resolves deleted users. Sets &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, resolves the picture URL, computes &amp;lt;code&amp;gt;mfa_enabled&amp;lt;/code&amp;gt;, loads &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · detail&lt;br /&gt;
| Extends &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;geo_organization: dict&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_by: dict | None&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;flags: list[str]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;is_service_account&amp;lt;/code&amp;gt;. Serializes &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; (cached &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;geo_organization&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;OrganizationReadSpec&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;flags&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;get_all_flags()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · self (&amp;lt;code&amp;gt;/users/getcurrentuser&amp;lt;/code&amp;gt;-style)&lt;br /&gt;
| Extends &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;is_superuser&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;qualification&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;doctor_experience_commenced_on&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;doctor_medical_council_registration&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;weekly_working_hours&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;alt_phone_number&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;date_of_birth&amp;lt;/code&amp;gt; (all nullable strings), &amp;lt;code&amp;gt;verified&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pf_endpoint&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;pf_p256dh&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;pf_auth&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;organizations: list[dict]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;facilities: list[dict]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;permissions: list[str]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;preferences: dict&amp;lt;/code&amp;gt;. Computes the caller&amp;#039;s organizations, facilities (excluding deleted), and resolved permission slugs&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PublicUserReadSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| read · public&lt;br /&gt;
| Base + &amp;lt;code&amp;gt;last_login&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;profile_picture_url&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;role_orgs: list[dict]&amp;lt;/code&amp;gt;. Minimal unauthenticated projection&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The password-reset flow uses plain-&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt; request/response DTOs (not &amp;lt;code&amp;gt;EMRResource&amp;lt;/code&amp;gt;, no model binding), all in &amp;lt;code&amp;gt;user/spec.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DTO&lt;br /&gt;
! Shape&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResetPasswordCheckRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ token: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResetPasswordConfirmRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ token: str, password: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResetPasswordResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ detail: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ResetPasswordRequestTokenRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ username: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== MFA specs ===&lt;br /&gt;
&lt;br /&gt;
Plain-&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt; DTOs in [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/mfa/spec.py &amp;lt;code&amp;gt;care/emr/resources/mfa/spec.py&amp;lt;/code&amp;gt;]. They carry no model binding and drive the TOTP/backup-code flow that writes &amp;lt;code&amp;gt;totp_secret&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;mfa_settings&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DTO&lt;br /&gt;
! Direction&lt;br /&gt;
! Shape&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TOTPSetupResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
| response&lt;br /&gt;
| &amp;lt;code&amp;gt;{ uri: str, secret_key: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TOTPVerifyRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| request&lt;br /&gt;
| &amp;lt;code&amp;gt;{ code: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TOTPVerifyResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
| response&lt;br /&gt;
| &amp;lt;code&amp;gt;{ backup_codes: list[str] }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PasswordVerifyRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| request&lt;br /&gt;
| &amp;lt;code&amp;gt;{ password: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MFALoginRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
| request&lt;br /&gt;
| &amp;lt;code&amp;gt;{ method: LoginMethod, code: str, temp_token: str }&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MFALoginResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
| response&lt;br /&gt;
| &amp;lt;code&amp;gt;{ access: str, refresh: str }&amp;lt;/code&amp;gt; (JWT pair)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Validation rules (write specs) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field&lt;br /&gt;
! Rule&lt;br /&gt;
! Source&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt;&lt;br /&gt;
| Matches &amp;lt;code&amp;gt;^[a-zA-Z0-9_-]{3,}$&amp;lt;/code&amp;gt;; must not already exist (checked against the entire queryset, including deleted)&lt;br /&gt;
| &amp;lt;code&amp;gt;UserCreateSpec.validate_username&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;phone_number&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must not already exist on any user&lt;br /&gt;
| &amp;lt;code&amp;gt;UserCreateSpec.validate_phone_number&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must not already exist; must pass Django &amp;lt;code&amp;gt;validate_email&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;UserCreateSpec.validate_user_email&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;password&amp;lt;/code&amp;gt;&lt;br /&gt;
| If provided, must pass Django &amp;lt;code&amp;gt;validate_password&amp;lt;/code&amp;gt; (else &amp;amp;quot;Password is too weak&amp;amp;quot;); &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; is allowed&lt;br /&gt;
| &amp;lt;code&amp;gt;UserCreateSpec.validate_password&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;gender&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must be a &amp;lt;code&amp;gt;GenderChoices&amp;lt;/code&amp;gt; member&lt;br /&gt;
| type annotation&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;geo_organization&amp;lt;/code&amp;gt;&lt;br /&gt;
| Must reference an existing &amp;lt;code&amp;gt;Organization&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;org_type=&amp;amp;quot;govt&amp;amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;UserUpdateSpec.perform_extra_deserialization&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Server-maintained behaviour ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt; on create — &amp;lt;code&amp;gt;UserCreateSpec.perform_extra_deserialization&amp;lt;/code&amp;gt; copies &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt; onto &amp;lt;code&amp;gt;obj._role_orgs&amp;lt;/code&amp;gt; so the view can apply role/organization assignments after the user is saved. It is not a DB column.&lt;br /&gt;
* &amp;lt;code&amp;gt;set_password&amp;lt;/code&amp;gt; — create hashes the supplied password via &amp;lt;code&amp;gt;obj.set_password(self.password)&amp;lt;/code&amp;gt;, or sets an unusable password when it is &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Cache — &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;@cacheable(use_base_manager=True)&amp;lt;/code&amp;gt;. Saving a &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; invalidates the cache via &amp;lt;code&amp;gt;post_save&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; is read through &amp;lt;code&amp;gt;model_from_cache(UserSpec, ...)&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;use_base_manager=True&amp;lt;/code&amp;gt; lets cached lookups resolve soft-deleted users.&lt;br /&gt;
* Computed read fields — &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; (from &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;profile_picture_url&amp;lt;/code&amp;gt; (resolved), &amp;lt;code&amp;gt;mfa_enabled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;flags&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;geo_organization&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt;, and the current-user &amp;lt;code&amp;gt;organizations&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;facilities&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;permissions&amp;lt;/code&amp;gt; are all populated in &amp;lt;code&amp;gt;perform_extra_serialization&amp;lt;/code&amp;gt;, never copied straight from columns.&lt;br /&gt;
&lt;br /&gt;
== Shared spec types ==&lt;br /&gt;
&lt;br /&gt;
Defined in &amp;lt;code&amp;gt;care/emr/resources/base.py&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;care/emr/resources/common/&amp;lt;/code&amp;gt;. No user spec binds these period and contact types; they belong to the shared resource vocabulary documented here for cross-reference.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type&lt;br /&gt;
! Shape&lt;br /&gt;
! Source&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PeriodSpec&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ start: datetime | None, end: datetime | None }&amp;lt;/code&amp;gt; — both must be timezone-aware; &amp;lt;code&amp;gt;start ≤ end&amp;lt;/code&amp;gt; enforced&lt;br /&gt;
| [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;base.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Period&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ id: str?, start: datetime?, end: datetime? }&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;extra=&amp;amp;quot;forbid&amp;amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
| [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/common/period.py &amp;lt;code&amp;gt;common/period.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ContactPoint&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;{ system: ContactPointSystemChoices, value: str, use: ContactPointUseChoices }&amp;lt;/code&amp;gt;&lt;br /&gt;
| [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/common/contact_point.py &amp;lt;code&amp;gt;common/contact_point.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PhoneNumber&amp;lt;/code&amp;gt;&lt;br /&gt;
| E.164 string (&amp;lt;code&amp;gt;PhoneNumberValidator&amp;lt;/code&amp;gt;)&lt;br /&gt;
| [&amp;lt;nowiki/&amp;gt;https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py &amp;lt;code&amp;gt;base.py&amp;lt;/code&amp;gt;]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ContactPointSystemChoices&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;phone&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fax&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pager&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;url&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sms&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;other&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;ContactPointUseChoices&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;home&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;work&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;temp&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;old&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mobile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Related models ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;Skill&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Instance-wide competency definition. Extends [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;name        → CharField(255), unique&lt;br /&gt;
description → TextField (nullable, default &amp;quot;&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== &amp;lt;code&amp;gt;UserSkill&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Through model joining &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Skill&amp;lt;/code&amp;gt;. Extends [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;user  → FK User (CASCADE, nullable)&lt;br /&gt;
skill → FK Skill (CASCADE, nullable)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;lt;code&amp;gt;unique_user_skill&amp;lt;/code&amp;gt; constraint blocks duplicate &amp;lt;code&amp;gt;(skill, user)&amp;lt;/code&amp;gt; pairs among non-deleted rows.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;UserFlag&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Feature flag attached to a single user. Extends &amp;lt;code&amp;gt;BaseFlag&amp;lt;/code&amp;gt; (a [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt;]] subclass with a &amp;lt;code&amp;gt;flag&amp;lt;/code&amp;gt; field).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;user → FK User (CASCADE)&lt;br /&gt;
flag → CharField(1024)  (inherited from BaseFlag)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;flag_type = FlagType.USER&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;unique_user_flag&amp;lt;/code&amp;gt; constraint blocks duplicate &amp;lt;code&amp;gt;(user, flag)&amp;lt;/code&amp;gt; pairs among non-deleted rows. Flags are read through &amp;lt;code&amp;gt;UserFlag.check_user_has_flag(user_id, flag_name)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;get_all_flags(user_id)&amp;lt;/code&amp;gt;, both cache-backed (TTL 1 day). &amp;lt;code&amp;gt;UserRetrieveSpec.flags&amp;lt;/code&amp;gt; surfaces these names as a &amp;lt;code&amp;gt;list[str]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;PlugConfig&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Slug-keyed configuration for installed plugs. Extends plain &amp;lt;code&amp;gt;models.Model&amp;lt;/code&amp;gt; (no audit/soft-delete fields).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;slug → CharField(255), unique&lt;br /&gt;
meta → JSONField (default {})&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== &amp;lt;code&amp;gt;MobileOTP&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Defined in &amp;lt;code&amp;gt;care/facility/models/patient.py&amp;lt;/code&amp;gt;. One-time password issued against a phone number for verification flows. Extends [[References/Base models &amp;amp;amp; conventions|&amp;lt;code&amp;gt;BaseModel&amp;lt;/code&amp;gt;]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;is_used      → BooleanField (default False)&lt;br /&gt;
phone_number → CharField(14)  (mobile_or_landline_number_validator)&lt;br /&gt;
otp          → CharField(10)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Methods &amp;amp;amp; save behaviour ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt; overrides neither &amp;lt;code&amp;gt;save()&amp;lt;/code&amp;gt; nor &amp;lt;code&amp;gt;delete()&amp;lt;/code&amp;gt;. Its helpers back the computed read fields:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get_cached_role_orgs()&amp;lt;/code&amp;gt; — returns &amp;lt;code&amp;gt;cached_role_orgs&amp;lt;/code&amp;gt; if set; otherwise loads from &amp;lt;code&amp;gt;OrganizationUser.get_cached_role_orgs(self.id)&amp;lt;/code&amp;gt; and persists it via &amp;lt;code&amp;gt;save(update_fields=[&amp;amp;quot;cached_role_orgs&amp;amp;quot;])&amp;lt;/code&amp;gt;. Read specs surface the result as &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;read_profile_picture_url()&amp;lt;/code&amp;gt; — resolves &amp;lt;code&amp;gt;profile_picture_url&amp;lt;/code&amp;gt; against &amp;lt;code&amp;gt;FACILITY_CDN&amp;lt;/code&amp;gt; or the S3 bucket endpoint; returns &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; when unset. Backs every read spec&amp;#039;s &amp;lt;code&amp;gt;profile_picture_url&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;is_mfa_enabled()&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; when &amp;lt;code&amp;gt;mfa_settings[&amp;amp;quot;totp&amp;amp;quot;][&amp;amp;quot;enabled&amp;amp;quot;]&amp;lt;/code&amp;gt; is set; surfaced as &amp;lt;code&amp;gt;mfa_enabled&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;full_name&amp;lt;/code&amp;gt; (property) — joins &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get_full_name()&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;suffix&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;check_username_exists(username)&amp;lt;/code&amp;gt; (static) — checks across the entire (including deleted) queryset; used by &amp;lt;code&amp;gt;UserCreateSpec.validate_username&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_all_flags()&amp;lt;/code&amp;gt; — delegates to &amp;lt;code&amp;gt;UserFlag.get_all_flags(self.id)&amp;lt;/code&amp;gt;; surfaced as &amp;lt;code&amp;gt;flags&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;CustomUserManager&amp;lt;/code&amp;gt; adds:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get_queryset()&amp;lt;/code&amp;gt; filters &amp;lt;code&amp;gt;deleted=False&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;get_entire_queryset()&amp;lt;/code&amp;gt; returns all rows.&lt;br /&gt;
* &amp;lt;code&amp;gt;create_superuser()&amp;lt;/code&amp;gt; forces &amp;lt;code&amp;gt;phone_number=&amp;amp;quot;+919696969696&amp;amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gender=&amp;amp;quot;non_binary&amp;amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;user_type=&amp;amp;quot;administrator&amp;amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;make_random_password()&amp;lt;/code&amp;gt; generates a secure password guaranteeing lower/upper/digit composition.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;UserFlag.save()&amp;lt;/code&amp;gt; (via &amp;lt;code&amp;gt;BaseFlag&amp;lt;/code&amp;gt;) validates the flag name against the registry and invalidates the per-flag and all-flags cache keys on every write.&lt;br /&gt;
&lt;br /&gt;
== API integration notes ==&lt;br /&gt;
&lt;br /&gt;
* The public identifier is &amp;lt;code&amp;gt;external_id&amp;lt;/code&amp;gt;, returned as &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;. Never key on the integer PK or &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt; alone.&lt;br /&gt;
* &amp;lt;code&amp;gt;CustomUserManager&amp;lt;/code&amp;gt; honours &amp;lt;code&amp;gt;deleted&amp;lt;/code&amp;gt;: soft-deleted users drop out of normal queries, but cached &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; lookups use the base manager (&amp;lt;code&amp;gt;use_base_manager=True&amp;lt;/code&amp;gt;) and can still resolve them — for example as a &amp;lt;code&amp;gt;created_by&amp;lt;/code&amp;gt; reference.&lt;br /&gt;
* Authorization is not stored on &amp;lt;code&amp;gt;User&amp;lt;/code&amp;gt;. Access resolves through the roles/permissions/organization system, and &amp;lt;code&amp;gt;cached_role_orgs&amp;lt;/code&amp;gt; is a platform-maintained cache — clients must not write it. New users supply &amp;lt;code&amp;gt;role_orgs&amp;lt;/code&amp;gt; (organization + role UUIDs) at create time.&lt;br /&gt;
* &amp;lt;code&amp;gt;mfa_settings&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;preferences&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;PlugConfig.meta&amp;lt;/code&amp;gt; are open JSON bags for evolving config without migrations. &amp;lt;code&amp;gt;mfa_settings&amp;lt;/code&amp;gt; is mutated by the MFA flow (&amp;lt;code&amp;gt;mfa/spec.py&amp;lt;/code&amp;gt;), not by user create/update.&lt;br /&gt;
* &amp;lt;code&amp;gt;is_service_account&amp;lt;/code&amp;gt; distinguishes machine/integration accounts from human users.&lt;br /&gt;
* Write through &amp;lt;code&amp;gt;UserCreateSpec&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;UserUpdateSpec&amp;lt;/code&amp;gt;; read through &amp;lt;code&amp;gt;UserSpec&amp;lt;/code&amp;gt; (list), &amp;lt;code&amp;gt;UserRetrieveSpec&amp;lt;/code&amp;gt; (detail), &amp;lt;code&amp;gt;CurrentUserRetrieveSpec&amp;lt;/code&amp;gt; (self), and &amp;lt;code&amp;gt;PublicUserReadSpec&amp;lt;/code&amp;gt; (public). Picture URLs, MFA status, roles, flags, and nested org/creator objects are all computed server-side.&lt;br /&gt;
&lt;br /&gt;
{{Related}}&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>