Lock SharePoint column, make field ReadOnly or ReadOnlyEnforced
Prevent SharePoint List filed editing from end user by making it read only
When a new site column is created, a SharePoint admin can set it as read only or as read only enforced to prevent the user of editing the data stored in the field. This can be done either through PowerShell or CSOM. You can see the onet.xml schema here and the description of the mentioned read only properties.
Lock item using SharePoint Framework ListView Command Set or Field Customizer
We can rely on modern SharePoint development using the SharePoint Framework to do that for us. SharePoint Framework Command Set like one created by @Alex Terentiev can be used to lock down a field. While the SharePoint Framework extensions are handy they cannot fully prevent the end user to change the value of field locked by front end code. Since the SharePoint Framework runs under the context of the user, users with higher permissions like site collection admin rights would still be able to bypass that restriction from the UI.
What if only system with SharePoint elevated permissions has to change a field value
There are cases where the field should be locked and editable only by a web service or job using CSOM or other server code that executes commands with elevated rights. Then we can set the field as read only or read only enforced with the help of PnP PowerShell.
A little experiment, read only field vs read only enforced
A quick and convenient way to change existing SharePoint site column attributes, lists or content types is to use PowerShell 5.0 and the PnP SharePoint PowerShell cmdlets. My experiment would include creation of a field, set it as read only and then set it as read only enforced. The initial step in the code below would include creation of field called 'Bio', content type and list from scratch.
At that point of the provisioning, the 'Bio' site column is visible and editable in the list I created. Now let's make it read only and push the update to all the SharePoint lists containing the site column.
After the script is run, the schema for the field looks like
Quick look at the SharePoint list edit form shows that the 'Bio' field is not present anymore
Quick look at the SharePoint list quick edit view shows that the 'Bio' field is displayed, but cannot be edited
The field is not even visible in the content type therefore end user cannot reveal it by changing content type column settings
It is also hidden in the SharePoint site column settings which makes it truly read only. It can still be listed programmatically if we get it with PowerShell Get-PnPField
Now, it is almost certain that can be modified by PowerShell, but how about front end code on behalf of the user such PnPJS. Let's test that using the SP Editor (Chrome extension).
Ok, that did not seem to work when executed on behalf of user. A test with PnP PowerShell on the other hand worked.
Is the field ReadOnly attribute a good fit preventing user edit, but ok for code with elevated rights?
The above PowerShell code worked and it was able to change the field read only value. So the ReadOnly field is a good fit. If we want to update a field from elevated CSOM code we can. A user can read the field value changes in a list view, but not modify them.
About the behavior of the field ReadOnlyEnforced attribute
There is also field attribute called ReadOnlyEnforced, but not much information about it. Let's experiment and see what will happen. This attribute has to be changed through the xml schema since there isn't a CSOM property for that.
How this affects the field now? I was able to add item manually as end user, also was able to add it with PnPJS and PnP PowerShell. Also the field is present in the edit form, settings content types and settings site columns sections. Now let's try to edit it with PnPJS.
I was not able to update the field using pnp js, neither from the edit form. How about PnP PowerShell then?
With field as ReadOnlyEnforced we can add new items with the field value filled-in, but not easily update it even with PowerShell
Didn't work either with PowerShell script, so seems that we can add item and have that field value filled-in, but it cannot easily be changed once created even with CSOM. I have not further tested that with Azure AD app principle instead of user admin account.
The point is clear, the ReadOnly and ReadOnlyEnforced SharePoint field attributes serve two different purposes. One behaves as end user read-only field able to change from system and the ReadOnlyEnforced behaves as add new value and forget about changing that. SharePoint site column with either of the attributes can still be shown in a SharePoint list view so the user can see its value, but not edit it.