SEBA-662 update xproto documentation

Change-Id: I7a6b812ac4c69c75533466442c3664f126a4af93
diff --git a/docs/dev/xproto.md b/docs/dev/xproto.md
index 8b10863..d50a941 100644
--- a/docs/dev/xproto.md
+++ b/docs/dev/xproto.md
@@ -144,7 +144,7 @@
 by a particular model.
 
 Currently supported model options include: `name`, `app_label`, `verbose_name`,
-`legacy`, `tosca_description`, `validators`, `plural`, `singular`, and
+`custom_python`, `tosca_description`, `validators`, `plural`, `singular`, and
 `gui_hidden`.
 
 The name option is a short name used to refer to your service. For example, in
@@ -169,16 +169,28 @@
 option verbose_name = "Virtual Subscriber Gateway Service";
 ```
 
+The `custom_python` option allows custom code to be attached to model.
+
 ```protobuf
-option app_label = "legacy"
+option custom_python = "True"
 ```
 
-The legacy option is for services that require custom Python code in their
-generated models. Without this option set, for any given model (`VSGService`)
-the toolchain generates model classes in a self-contained file
-(`vsgservice.py`).  With this option set, the toolchain generates the models in
-a file called `vsgservice_decl.py`. All of the models in this file have the
-suffix `_decl`.  It is then up to the service developer to provide the final
+The `custom_python` option is for services that require custom Python code in their
+generated models. This option may either be specified at the file level and apply
+to all models within a file, or individually at the model level within a file.
+When custom python models are in use, the following changes occur to the generative
+toolchain,
+
+* Models are created in a file called "models_decl.py" (or modelname_decl.py depending
+  on whether you're working on a service or in the core).
+* Autogenerated models have the suffix `_decl` attached to them, for example
+  `VSGService_decl`.
+* If there's a mix of custom_python and non-custom_python models in the same file, then
+  the non-custom_python models will automatically receive stubs that convert them
+  from the `_decl` model to the non-`_decl` model.
+
+Once the developer has designated some models as having custom python, it is then
+up to the service developer to provide the final
 models. The code below gives an example of custom models that inherit from such
 intermediate `decl` models:
 
@@ -192,6 +204,16 @@
 You can use the xproto `service_extender` target to generate a stub for your
 final model definitions.
 
+> NOTE: As custom_python code ends up extending the XOS core with service-specific code,
+> it is recommended to avoid using custom_python if an alternative exists to achieve
+> the same functionality. For example, `model_policies` are another way to attach
+> service-specific features to models, and run in the synchronizer rather than in the
+> core.
+>
+> NOTE: The `custom_python` option was previously called `legacy`, and you may
+> still encounter some services that use the keyword `legacy` instead of
+> custom_python.
+
 The plural and singular options provide the grammatically correct plural and
 singular forms of your model name to ensure that autogenerated API endpoints
 are valid.
@@ -273,6 +295,19 @@
 option max_value = 100;
 ```
 
+Designates a field as `feedback_state`, by default preventing it from being updated using GUI
+or CLI tools.
+
+```protobuf
+option feedback_state = True;
+```
+
+Designates a field as `bookkeeping_state`, by default hiding it from GUI or CLI tools.
+
+```protobuf
+option bookkeeping_state = True;
+```
+
 Do not display this field in the GUI (also available at the model level):
 
 ```protobuf
@@ -357,16 +392,22 @@
 Field names use lower-case with underscores separating names. Examples of valid
 field names are: name, `disk_format`, `controller_format`.
 
-### Declarative vs Feedback State
+### Declarative vs Feedback vs Bookkeeping State
 
 By convention, the fields that make up a model are classified as holding one of
-two kinds of state: *declarative* and *feedback*.
+three kinds of state: *declarative*, *feedback*, or *bookkeeping*.
 
 Fields set by the operator to specify (declare) the expected state of CORD's
 underlying components are said to hold *declarative state*.  In contrast,
 fields that record operational data reported from CORD's underlying (backend)
 components are said to hold *feedback state*.
 
+*bookkeeping state* are fields that are typically used by the synchronizer
+framework or by a synchronizer to hold information about the model that is
+useful to the synchronizer, but not to the operator. For example, timestamps
+that are used to track when models are dirty, error retry information,
+etc.
+
 For more information about declarative and feedback state, and the role they
 play in synchornizing the data model with the backend components, read about
 the [Synchronizer Architecture](sync_arch.md).