diff --git a/aip/general/0216.md b/aip/general/0216.md index 5233dfcacc..1515061ec9 100644 --- a/aip/general/0216.md +++ b/aip/general/0216.md @@ -123,6 +123,44 @@ message PublishBookRequest { - The comment for the field **should** document the resource pattern. - Other fields **may** be included. +### Declarative-friendly state transitions + +If a resource's state can be modified by [declarative tooling][aip-128], it +**should** expose a separate `desired_state` field taking the same enum type. + +```proto +message Book { + enum State { + STATE_UNSPECIFIED = 0; + UNPUBLISHED = 1; + PUBLISHING = 2; + PUBLISHED = 3; + } + + State state = 1 [(google.api.field_behaviopr = OUTPUT_ONLY)]; + State desired_state = 2; +} +``` + +- The `state` field's output **may** change to more granular + [active states](#common-states) to indicate progress toward the `desired_state`. +- The `desired_state` field **must** only allow [resting state](#common-states) + enum values. +- Attempting to set `desired_state` to an [active state](#common-states) **must** + error with `INVALID_ARGUMENT` (HTTP 400). +- Attempting to set `desired_state` to a state that cannot be transitioned to + from the current state **must** error with `FAILED_PRECONDITION` (HTTP 400). +- A [long-running][] operation **must not** complete until the `state` has + reached the `desired_state` (or **must** error if it cannot). +- If a resource supports both declarative `desired_state` and imperative + [state transition methods](#state-transition-methods), executing a state + transition method **should** modify the desired state appropriately. +- If a resource is created without `desired_state`, the field **must** default + to the same resting value as `state`. +- If an out-of-band event causes the resting `state` of the resource to change, + the `desired_state` **must** be changed to match. This does not apply to + a temporary condition that will return to the same resting state. + ## Additional Guidance ### Default value @@ -239,4 +277,5 @@ necessary. - **2019-07-18**: Added explicit guidance on the unspecified value. [aip-126]: ./0126.md +[aip-128]: ./0128.md [long-running]: ./0151.md