|
| 1 | +--- |
| 2 | +id: 129 |
| 3 | +state: draft |
| 4 | +created: 2023-09-20 |
| 5 | +placement: |
| 6 | + category: resource-design |
| 7 | + order: 65 |
| 8 | +--- |
| 9 | + |
| 10 | +# Server-Modified Values and Defaults |
| 11 | + |
| 12 | +Services often provide default values for resource fields, and occasionally |
| 13 | +normalize the user input before returning it in the response. The guidance |
| 14 | +herein describes how services document such behavior for the benefit of |
| 15 | +consumers. |
| 16 | + |
| 17 | +## Guidance |
| 18 | + |
| 19 | +### Single Owner Fields |
| 20 | + |
| 21 | +Fields **must** have a single owner, whether that is the client or the server. |
| 22 | +Server owned fields **must** be indicated with the `OUTPUT_ONLY` field_behavior. |
| 23 | +All other types of fields **must** be considered to be owned by the client. The |
| 24 | +server **must** respect the value (or lack thereof) for all client owned fields |
| 25 | +and not modify them. |
| 26 | + |
| 27 | +### Effective Values |
| 28 | + |
| 29 | +There are instances where a service will allocate, generate, or calculate a |
| 30 | +value if the client chooses not to specify one. For example: a client creates a |
| 31 | +virtual machine without specifying a static IP address for the virtual machine |
| 32 | +to be available on. Such a scenario is opting into dynamic IP address |
| 33 | +allocation. |
| 34 | + |
| 35 | +Some examples of these types of fields are ones that are: |
| 36 | + |
| 37 | +* generated (UUID) |
| 38 | +* allocated (dynamic IP address) |
| 39 | +* assigned (most recent software package version) |
| 40 | + |
| 41 | +An attribute with an effective value ***must*** be expressed as two fields in |
| 42 | +the API: |
| 43 | +* a mutable field that can be optionally set by the user and **must not** be |
| 44 | +modified by the service |
| 45 | +* an `OUTPUT_ONLY` field that records the effective value decided on by the |
| 46 | +service |
| 47 | + |
| 48 | +Example: |
| 49 | +```proto |
| 50 | +message VirtualMachine { |
| 51 | + … |
| 52 | + string ip_address = 4; |
| 53 | + string effective_ip_address = 5 [ |
| 54 | + (google.api.field_behavior) = OUTPUT_ONLY |
| 55 | + ]; |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +#### Naming |
| 60 | + |
| 61 | +Effective values **must** be named by prefixing `effective_` to the mutable |
| 62 | +field's name. |
| 63 | + |
| 64 | +### User-Specified Fields |
| 65 | + |
| 66 | +For user-specified fields, the value in response from the service **must** be |
| 67 | +the same as provided by the create or update request. For string fields this |
| 68 | +means returning the value unchanged, with one exception: |
| 69 | + |
| 70 | +* When a string field has a data type annotation, a normalized string that |
| 71 | + represents the given value **may** be returned. |
| 72 | + |
| 73 | +### Normalizations |
| 74 | + |
| 75 | +A field that is normalized by the service **must** be annotated with the |
| 76 | +`google.api.field_info` extension. See [AIP-202](aip-202) for guidance on using |
| 77 | +this extension The allowed set of normalizations includes the following formats: |
| 78 | + |
| 79 | +* uuid |
| 80 | +* ipv4 |
| 81 | +* ipv6 |
| 82 | +* email |
| 83 | + |
| 84 | +Normalizations on fields **must** be described using the `google.api.field_info` |
| 85 | +annotation. |
| 86 | + |
| 87 | +## Rationale |
| 88 | + |
| 89 | +Server-modified and default values often make it harder to implement |
| 90 | +[state-driven clients](state-driven-clients). These clients are often unable to |
| 91 | +tell when their desired state matches the current state for these fields, as the |
| 92 | +rules by which a server may modify and return values are complex, not public, |
| 93 | +and not repeatable. |
| 94 | + |
| 95 | +### Rationale for Single Owner Fields |
| 96 | + |
| 97 | +When fields do not have a single owner they can cause issues for |
| 98 | +[state-driven clients](state-driven-clients). These clients may attempt to set |
| 99 | +values for fields that are overwritten by server set values, leading to the |
| 100 | +client entering an infinite loop to correct the change. |
| 101 | + |
| 102 | +### Rationale for Naming |
| 103 | + |
| 104 | +Consistent naming is important for identifying standard behavior across APIs |
| 105 | +and fields. Programmatic association between user-specified and effective values |
| 106 | +depends on consistent naming. |
| 107 | + |
| 108 | +### Rationale for Normalizations |
| 109 | + |
| 110 | +Normalizations are important to allow services to store and return values in a |
| 111 | +standard way while communicating to clients what changes are semantically |
| 112 | +identical. Normalizing a value on the service side allows the service to accept |
| 113 | +a wider range of semantically identical inputs without needing to maintain every |
| 114 | +value as a raw string. Surfacing the normalization that is being applied to |
| 115 | +clients allows for client side comparison of sent and retrieved values to check |
| 116 | +for differences. |
| 117 | + |
| 118 | +For example, in a resource that accepts an email address on a particular field |
| 119 | +a client may specify a given email address in a variety of ways. For the email |
| 120 | +`ada@example.com` a client may choose to specify `ADA@example.com`, |
| 121 | +`aDa@example.com`, or `AdA@example.com`. These are semantically identical and |
| 122 | +*should* all be accepted by the service. The service then may choose to |
| 123 | +normalize the email address for storage and retrieval through downcasing or |
| 124 | +canonicalization. Importantly, the information surfaced to clients on the |
| 125 | +normalization of a field will not describe the normalization algorithm itself, |
| 126 | +but instead the comparison method used to accurately compute if two values |
| 127 | +should be considered equal. |
| 128 | + |
| 129 | +### Rationale for Field Value Handling |
| 130 | + |
| 131 | +For fields not using an allowed normalization, |
| 132 | +[Declarative clients][] will not be able to identify which changes are |
| 133 | +semantically meaningful. When a [Declarative client][Declarative clients] |
| 134 | +sends a particular value it will ensure that the value is being returned by the |
| 135 | +service to validate it was set correctly. |
| 136 | + |
| 137 | +[Declarative clients]: ./0009#declarative-clients |
| 138 | +[aip-202]: ./202.md |
| 139 | + |
| 140 | +- |
| 141 | + |
| 142 | +<!-- prettier-ignore-start --> |
| 143 | +[aip-180]: ./0180.md |
| 144 | +[state-driven-clients]: ./009.md#state-driven-clients |
| 145 | +<!-- prettier-ignore-end --> |
0 commit comments