Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server-modified-values): Import AEP-129 from AIP-129 #201

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions aep/general/0129/aep.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Server-Modified Values and Defaults

Services often provide default values for resource fields, and occasionally
normalize the user input before returning it in the response. The guidance
herein describes how services document such behavior for the benefit of
consumers.

## Guidance

### Single Owner Fields

Fields **must** have a single owner, whether that is the client or the server.
Server owned fields **must** be indicated with the `OUTPUT_ONLY` field_behavior.
All other types of fields **must** be considered to be owned by the client. The
server **must** respect the value (or lack thereof) for all client owned fields
and not modify them.

### Effective Values

There are instances where a service will allocate, generate, or calculate a
value if the client chooses not to specify one. For example: a client creates a
virtual machine without specifying a static IP address for the virtual machine
to be available on. Such a scenario is opting into dynamic IP address
allocation.

Some examples of these types of fields are ones that are:

* generated (UUID)
* allocated (dynamic IP address)
* assigned (most recent software package version)

An attribute with an effective value ***must*** be expressed as two fields in
the API:

* a mutable field that can be optionally set by the user and **must not** be
modified by the service
* an `OUTPUT_ONLY` field that records the effective value decided on by the
service

Example:
```proto
message VirtualMachine {
string ip_address = 4;
string effective_ip_address = 5 [
(google.api.field_behavior) = OUTPUT_ONLY
];
}
```

#### Naming

Effective values **must** be named by prefixing `effective_` to the mutable
field's name.

### User-Specified Fields

For user-specified fields, the value in response from the service **must** be
the same as provided by the create or update request. For string fields this
means returning the value unchanged, with one exception:

* When a string field has a data type annotation, a normalized string that
represents the given value **may** be returned.

### Normalizations

A field that is normalized by the service **must** be annotated with the
`google.api.field_info` extension. See [AIP-202](aip-202) for guidance on using
this extension The allowed set of normalizations includes the following formats:

* uuid
* ipv4
* ipv6
* email

Normalizations on fields **must** be described using the `google.api.field_info`
annotation.

## Rationale

Server-modified and default values often make it harder to implement
[declarative clients][]. These clients are often unable to
tell when their desired state matches the current state for these fields, as the
rules by which a server may modify and return values are complex, not public,
and not repeatable.

### Rationale for Single Owner Fields

When fields do not have a single owner they can cause issues for
[declarative clients][]. These clients may attempt to set
values for fields that are overwritten by server set values, leading to the
client entering an infinite loop to correct the change.

### Rationale for Naming

Consistent naming is important for identifying standard behavior across APIs
and fields. Programmatic association between user-specified and effective values
depends on consistent naming.

### Rationale for Normalizations

Normalizations are important to allow services to store and return values in a
standard way while communicating to clients what changes are semantically
identical. Normalizing a value on the service side allows the service to accept
a wider range of semantically identical inputs without needing to maintain every
value as a raw string. Surfacing the normalization that is being applied to
clients allows for client side comparison of sent and retrieved values to check
for differences.

For example, in a resource that accepts an email address on a particular field
a client may specify a given email address in a variety of ways. For the email
`ada@example.com` a client may choose to specify `ADA@example.com`,
`aDa@example.com`, or `AdA@example.com`. These are semantically identical and
*should* all be accepted by the service. The service then may choose to
normalize the email address for storage and retrieval through downcasing or
canonicalization. Importantly, the information surfaced to clients on the
normalization of a field will not describe the normalization algorithm itself,
but instead the comparison method used to accurately compute if two values
should be considered equal.

### Rationale for Field Value Handling

For fields not using an allowed normalization,
[Declarative clients][] will not be able to identify which changes are
semantically meaningful. When a [Declarative client][Declarative clients]
sends a particular value it will ensure that the value is being returned by the
service to validate it was set correctly.

## Changelog

- **2024-07-11:** Imported from https://google.aip.dev/129

[Declarative clients]: ./0009.md#declarative-clients
[aip-202]: ./0202.md

<!-- prettier-ignore-start -->
[aip-180]: ./0180.md
<!-- prettier-ignore-end -->
7 changes: 7 additions & 0 deletions aep/general/0129/aep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
id: 129
state: approved
slug: server-modified-values
created: 2024-07-11
placement:
category: standard-methods
Loading