Skip to content

Commit 8e07336

Browse files
authored
Add AIP 129 for server modified values (#1144)
1 parent 43e2d77 commit 8e07336

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

aip/general/0129.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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

Comments
 (0)