We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Provide documentation about user_groups and permission changes
### Issue description

If we edit permissions for User Groups, such as to make different items viewable on django admin, this requires a very specific set of instructions that is only documentated inside user group migration files. We should reference this documentation somewhere else in our developer readme so it's clear what is needed to be done if you ever change permissions in the future.

 We had a case where permissions were changed and it wasn't clear what needed to be done (make a manual migration). The developers lost time trying to figure out why permissions didn't show and why running makemigrations changed nothing. I suggest adding an inline code comment around where permissions are set in user_groups too that points to documentation in developer readme. This may save future developer's time.

### Acceptance criteria

- [ ] update developer documentation (inline and md) about user_group/ permission changes

### Additional context
the migration files that have documentation about this are all ones that say _create_groups_v (followed by a number), such as 0075_create_groups_v08.py. See those for the current documentation and note that this was hard for developers to find.
[Slack thread](https://cisa-corp.slack.com/archives/C05BGB4L5NF/p1709939481415349)

### Links to other issues

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/registrar/models/user_group.py`
Content:
```
1 from django.contrib.auth.models import Group
2 import logging
3 
4 logger = logging.getLogger(__name__)
5 
6 
7 class UserGroup(Group):
8     class Meta:
9         verbose_name = "User group"
10         verbose_name_plural = "User groups"
11 
12     def create_cisa_analyst_group(apps, schema_editor):
13         """This method gets run from a data migration."""
14 
15         # Hard to pass self to these methods as the calls from migrations
16         # are only expecting apps and schema_editor, so we'll just define
17         # apps, schema_editor in the local scope instead
18         CISA_ANALYST_GROUP_PERMISSIONS = [
19             {
20                 "app_label": "auditlog",
21                 "model": "logentry",
22                 "permissions": ["view_logentry"],
23             },
24             {
25                 "app_label": "registrar",
26                 "model": "contact",
27                 "permissions": ["change_contact"],
28             },
29             {
30                 "app_label": "registrar",
31                 "model": "domainrequest",
32                 "permissions": ["change_domainrequest"],
33             },
34             {
35                 "app_label": "registrar",
36                 "model": "domain",
37                 "permissions": ["view_domain"],
38             },
39             {
40                 "app_label": "registrar",
41                 "model": "draftdomain",
42                 "permissions": ["change_draftdomain"],
43             },
44             {
45                 "app_label": "registrar",
46                 "model": "user",
47                 "permissions": ["analyst_access_permission", "change_user"],
48             },
49             {
50                 "app_label": "registrar",
51                 "model": "domaininvitation",
52                 "permissions": ["add_domaininvitation", "view_domaininvitation"],
53             },
54             {
55                 "app_label": "registrar",
56                 "model": "website",
57                 "permissions": ["change_website"],
58             },
59             {
60                 "app_label": "registrar",
61                 "model": "userdomainrole",
62                 "permissions": ["view_userdomainrole", "delete_userdomainrole"],
63             },
64             {
65                 "app_label": "registrar",
66                 "model": "verifiedbystaff",
67                 "permissions": ["add_verifiedbystaff", "change_verifiedbystaff", "delete_verifiedbystaff"],
68             },
69             {
70                 "app_label": "registrar",
71                 "model": "federalagency",
72                 "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"],
73             },
74         ]
75 
76         # Avoid error: You can't execute queries until the end
77         # of the 'atomic' block.
78         # From django docs:
79         # https://docs.djangoproject.com/en/4.2/topics/migrations/#data-migrations
80         # We can’t import the Person model directly as it may be a newer
81         # version than this migration expects. We use the historical version.
82         ContentType = apps.get_model("contenttypes", "ContentType")
83         Permission = apps.get_model("auth", "Permission")
84         UserGroup = apps.get_model("registrar", "UserGroup")
85 
86         logger.info("Going to create the Analyst Group")
87         try:
88             cisa_analysts_group, _ = UserGroup.objects.get_or_create(
89                 name="cisa_analysts_group",
90             )
91 
92             cisa_analysts_group.permissions.clear()
93 
94             for permission in CISA_ANALYST_GROUP_PERMISSIONS:
95                 app_label = permission["app_label"]
96                 model_name = permission["model"]
97                 permissions = permission["permissions"]
98 
99                 # Retrieve the content type for the app and model
100                 content_type = ContentType.objects.get(app_label=app_label, model=model_name)
101 
102                 # Retrieve the permissions based on their codenames
103                 permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)
104 
105                 # Assign the permissions to the group
106                 cisa_analysts_group.permissions.add(*permissions)
107 
108                 # Convert the permissions QuerySet to a list of codenames
109                 permission_list = list(permissions.values_list("codename", flat=True))
110 
111                 logger.debug(
112                     app_label
113                     + " | "
114                     + model_name
115                     + " | "
116                     + ", ".join(permission_list)
117                     + " added to group "
118                     + cisa_analysts_group.name
119                 )
120 
121                 cisa_analysts_group.save()
122                 logger.debug("CISA Analyst permissions added to group " + cisa_analysts_group.name)
123         except Exception as e:
124             logger.error(f"Error creating analyst permissions group: {e}")
125 
126     def create_full_access_group(apps, schema_editor):
127         """This method gets run from a data migration."""
128 
129         Permission = apps.get_model("auth", "Permission")
130         UserGroup = apps.get_model("registrar", "UserGroup")
131 
132         logger.info("Going to create the Full Access Group")
133         try:
134             full_access_group, _ = UserGroup.objects.get_or_create(
135                 name="full_access_group",
136             )
137             # Get all available permissions
138             all_permissions = Permission.objects.all()
139 
140             # Assign all permissions to the group
141             full_access_group.permissions.add(*all_permissions)
142 
143             full_access_group.save()
144             logger.debug("All permissions added to group " + full_access_group.name)
145         except Exception as e:
146             logger.error(f"Error creating full access group: {e}")
147
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py
--- a/src/registrar/models/user_group.py
+++ b/src/registrar/models/user_group.py
@@ -5,6 +5,11 @@
 
 
 class UserGroup(Group):
+    """
+    UserGroup sets read and write permissions for superusers (who have full access)
+    and analysts. For more details, see the dev docs for user-permissions.
+    """
+
     class Meta:
         verbose_name = "User group"
         verbose_name_plural = "User groups"

{"golden_diff": "diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py\n--- a/src/registrar/models/user_group.py\n+++ b/src/registrar/models/user_group.py\n@@ -5,6 +5,11 @@\n \n \n class UserGroup(Group):\n+    \"\"\"\n+    UserGroup sets read and write permissions for superusers (who have full access)\n+    and analysts. For more details, see the dev docs for user-permissions.\n+    \"\"\"\n+\n     class Meta:\n         verbose_name = \"User group\"\n         verbose_name_plural = \"User groups\"\n", "issue": "Provide documentation about user_groups and permission changes\n### Issue description\r\n\r\nIf we edit permissions for User Groups, such as to make different items viewable on django admin, this requires a very specific set of instructions that is only documentated inside user group migration files. We should reference this documentation somewhere else in our developer readme so it's clear what is needed to be done if you ever change permissions in the future.\r\n\r\n We had a case where permissions were changed and it wasn't clear what needed to be done (make a manual migration). The developers lost time trying to figure out why permissions didn't show and why running makemigrations changed nothing. I suggest adding an inline code comment around where permissions are set in user_groups too that points to documentation in developer readme. This may save future developer's time.\r\n\r\n### Acceptance criteria\r\n\r\n- [ ] update developer documentation (inline and md) about user_group/ permission changes\r\n\r\n### Additional context\r\nthe migration files that have documentation about this are all ones that say _create_groups_v (followed by a number), such as 0075_create_groups_v08.py. See those for the current documentation and note that this was hard for developers to find.\r\n[Slack thread](https://cisa-corp.slack.com/archives/C05BGB4L5NF/p1709939481415349)\r\n\r\n### Links to other issues\r\n\r\n_No response_\n", "before_files": [{"content": "from django.contrib.auth.models import Group\nimport logging\n\nlogger = logging.getLogger(__name__)\n\n\nclass UserGroup(Group):\n    class Meta:\n        verbose_name = \"User group\"\n        verbose_name_plural = \"User groups\"\n\n    def create_cisa_analyst_group(apps, schema_editor):\n        \"\"\"This method gets run from a data migration.\"\"\"\n\n        # Hard to pass self to these methods as the calls from migrations\n        # are only expecting apps and schema_editor, so we'll just define\n        # apps, schema_editor in the local scope instead\n        CISA_ANALYST_GROUP_PERMISSIONS = [\n            {\n                \"app_label\": \"auditlog\",\n                \"model\": \"logentry\",\n                \"permissions\": [\"view_logentry\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"contact\",\n                \"permissions\": [\"change_contact\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domainrequest\",\n                \"permissions\": [\"change_domainrequest\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domain\",\n                \"permissions\": [\"view_domain\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"draftdomain\",\n                \"permissions\": [\"change_draftdomain\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"user\",\n                \"permissions\": [\"analyst_access_permission\", \"change_user\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domaininvitation\",\n                \"permissions\": [\"add_domaininvitation\", \"view_domaininvitation\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"website\",\n                \"permissions\": [\"change_website\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"userdomainrole\",\n                \"permissions\": [\"view_userdomainrole\", \"delete_userdomainrole\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"verifiedbystaff\",\n                \"permissions\": [\"add_verifiedbystaff\", \"change_verifiedbystaff\", \"delete_verifiedbystaff\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"federalagency\",\n                \"permissions\": [\"add_federalagency\", \"change_federalagency\", \"delete_federalagency\"],\n            },\n        ]\n\n        # Avoid error: You can't execute queries until the end\n        # of the 'atomic' block.\n        # From django docs:\n        # https://docs.djangoproject.com/en/4.2/topics/migrations/#data-migrations\n        # We can\u2019t import the Person model directly as it may be a newer\n        # version than this migration expects. We use the historical version.\n        ContentType = apps.get_model(\"contenttypes\", \"ContentType\")\n        Permission = apps.get_model(\"auth\", \"Permission\")\n        UserGroup = apps.get_model(\"registrar\", \"UserGroup\")\n\n        logger.info(\"Going to create the Analyst Group\")\n        try:\n            cisa_analysts_group, _ = UserGroup.objects.get_or_create(\n                name=\"cisa_analysts_group\",\n            )\n\n            cisa_analysts_group.permissions.clear()\n\n            for permission in CISA_ANALYST_GROUP_PERMISSIONS:\n                app_label = permission[\"app_label\"]\n                model_name = permission[\"model\"]\n                permissions = permission[\"permissions\"]\n\n                # Retrieve the content type for the app and model\n                content_type = ContentType.objects.get(app_label=app_label, model=model_name)\n\n                # Retrieve the permissions based on their codenames\n                permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)\n\n                # Assign the permissions to the group\n                cisa_analysts_group.permissions.add(*permissions)\n\n                # Convert the permissions QuerySet to a list of codenames\n                permission_list = list(permissions.values_list(\"codename\", flat=True))\n\n                logger.debug(\n                    app_label\n                    + \" | \"\n                    + model_name\n                    + \" | \"\n                    + \", \".join(permission_list)\n                    + \" added to group \"\n                    + cisa_analysts_group.name\n                )\n\n                cisa_analysts_group.save()\n                logger.debug(\"CISA Analyst permissions added to group \" + cisa_analysts_group.name)\n        except Exception as e:\n            logger.error(f\"Error creating analyst permissions group: {e}\")\n\n    def create_full_access_group(apps, schema_editor):\n        \"\"\"This method gets run from a data migration.\"\"\"\n\n        Permission = apps.get_model(\"auth\", \"Permission\")\n        UserGroup = apps.get_model(\"registrar\", \"UserGroup\")\n\n        logger.info(\"Going to create the Full Access Group\")\n        try:\n            full_access_group, _ = UserGroup.objects.get_or_create(\n                name=\"full_access_group\",\n            )\n            # Get all available permissions\n            all_permissions = Permission.objects.all()\n\n            # Assign all permissions to the group\n            full_access_group.permissions.add(*all_permissions)\n\n            full_access_group.save()\n            logger.debug(\"All permissions added to group \" + full_access_group.name)\n        except Exception as e:\n            logger.error(f\"Error creating full access group: {e}\")\n", "path": "src/registrar/models/user_group.py"}], "after_files": [{"content": "from django.contrib.auth.models import Group\nimport logging\n\nlogger = logging.getLogger(__name__)\n\n\nclass UserGroup(Group):\n    \"\"\"\n    UserGroup sets read and write permissions for superusers (who have full access)\n    and analysts. For more details, see the dev docs for user-permissions.\n    \"\"\"\n\n    class Meta:\n        verbose_name = \"User group\"\n        verbose_name_plural = \"User groups\"\n\n    def create_cisa_analyst_group(apps, schema_editor):\n        \"\"\"This method gets run from a data migration.\"\"\"\n\n        # Hard to pass self to these methods as the calls from migrations\n        # are only expecting apps and schema_editor, so we'll just define\n        # apps, schema_editor in the local scope instead\n        CISA_ANALYST_GROUP_PERMISSIONS = [\n            {\n                \"app_label\": \"auditlog\",\n                \"model\": \"logentry\",\n                \"permissions\": [\"view_logentry\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"contact\",\n                \"permissions\": [\"change_contact\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domaininformation\",\n                \"permissions\": [\"change_domaininformation\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domainrequest\",\n                \"permissions\": [\"change_domainrequest\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domain\",\n                \"permissions\": [\"view_domain\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"draftdomain\",\n                \"permissions\": [\"change_draftdomain\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"user\",\n                \"permissions\": [\"analyst_access_permission\", \"change_user\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"domaininvitation\",\n                \"permissions\": [\"add_domaininvitation\", \"view_domaininvitation\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"website\",\n                \"permissions\": [\"change_website\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"userdomainrole\",\n                \"permissions\": [\"view_userdomainrole\", \"delete_userdomainrole\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"verifiedbystaff\",\n                \"permissions\": [\"add_verifiedbystaff\", \"change_verifiedbystaff\", \"delete_verifiedbystaff\"],\n            },\n            {\n                \"app_label\": \"registrar\",\n                \"model\": \"federalagency\",\n                \"permissions\": [\"add_federalagency\", \"change_federalagency\", \"delete_federalagency\"],\n            },\n        ]\n\n        # Avoid error: You can't execute queries until the end\n        # of the 'atomic' block.\n        # From django docs:\n        # https://docs.djangoproject.com/en/4.2/topics/migrations/#data-migrations\n        # We can\u2019t import the Person model directly as it may be a newer\n        # version than this migration expects. We use the historical version.\n        ContentType = apps.get_model(\"contenttypes\", \"ContentType\")\n        Permission = apps.get_model(\"auth\", \"Permission\")\n        UserGroup = apps.get_model(\"registrar\", \"UserGroup\")\n\n        logger.info(\"Going to create the Analyst Group\")\n        try:\n            cisa_analysts_group, _ = UserGroup.objects.get_or_create(\n                name=\"cisa_analysts_group\",\n            )\n\n            cisa_analysts_group.permissions.clear()\n\n            for permission in CISA_ANALYST_GROUP_PERMISSIONS:\n                app_label = permission[\"app_label\"]\n                model_name = permission[\"model\"]\n                permissions = permission[\"permissions\"]\n\n                # Retrieve the content type for the app and model\n                content_type = ContentType.objects.get(app_label=app_label, model=model_name)\n\n                # Retrieve the permissions based on their codenames\n                permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)\n\n                # Assign the permissions to the group\n                cisa_analysts_group.permissions.add(*permissions)\n\n                # Convert the permissions QuerySet to a list of codenames\n                permission_list = list(permissions.values_list(\"codename\", flat=True))\n\n                logger.debug(\n                    app_label\n                    + \" | \"\n                    + model_name\n                    + \" | \"\n                    + \", \".join(permission_list)\n                    + \" added to group \"\n                    + cisa_analysts_group.name\n                )\n\n                cisa_analysts_group.save()\n                logger.debug(\"CISA Analyst permissions added to group \" + cisa_analysts_group.name)\n        except Exception as e:\n            logger.error(f\"Error creating analyst permissions group: {e}\")\n\n    def create_full_access_group(apps, schema_editor):\n        \"\"\"This method gets run from a data migration.\"\"\"\n\n        Permission = apps.get_model(\"auth\", \"Permission\")\n        UserGroup = apps.get_model(\"registrar\", \"UserGroup\")\n\n        logger.info(\"Going to create the Full Access Group\")\n        try:\n            full_access_group, _ = UserGroup.objects.get_or_create(\n                name=\"full_access_group\",\n            )\n            # Get all available permissions\n            all_permissions = Permission.objects.all()\n\n            # Assign all permissions to the group\n            full_access_group.permissions.add(*all_permissions)\n\n            full_access_group.save()\n            logger.debug(\"All permissions added to group \" + full_access_group.name)\n        except Exception as e:\n            logger.error(f\"Error creating full access group: {e}\")\n", "path": "src/registrar/models/user_group.py"}]}