From 85e49bf84748446d2d4f16da4cc4a8afb8bbe9d9 Mon Sep 17 00:00:00 2001 From: noahdietz Date: Thu, 18 Apr 2024 11:44:22 -0700 Subject: [PATCH 1/5] feat(AIP-202): add Type References section --- aip/general/0146.md | 21 +++++++++++++++++++++ aip/general/0202.md | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/aip/general/0146.md b/aip/general/0146.md index 08bd9cc672..4545e8c5f1 100644 --- a/aip/general/0146.md +++ b/aip/general/0146.md @@ -88,8 +88,29 @@ which is an often-unfamiliar process. Because of this, `Any` **should not** be used unless other options are infeasible. +If an `Any` is used and its set of possible types is controlled by the service, +it **must** be annotated with the type(s) it references. See +[AIP-202 Type References][typeref] for more details. + +## Rationale + +### Declaring `Any` type references + +At runtime, an `Any` will have the fully-qualified type name in the `type_url` +field to enable the runtime consumer to look up the descriptor and unpack the +message. However, there is no machine-readable indicator in the API +specification itself as to what type(s) could possible be packed in a given +`Any` field. This prevents development of static analysis and runtime compliance +tools, as well as accurate documentation and client library support. As such, an +annotation is necessary to forward declare what an `Any` could contain. + +## Changelog + +- **2024-04-18:** Add `Any` type reference requirement and rationale. + [any]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/any.proto [struct]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/struct.proto [JSONSchema]: https://json-schema.org/ +[typeref]: ./0202.md#type-references diff --git a/aip/general/0202.md b/aip/general/0202.md index ede221b359..4fa6d0fb74 100644 --- a/aip/general/0202.md +++ b/aip/general/0202.md @@ -81,6 +81,33 @@ backwards compatible. Any new `FieldInfo.Format` value **must** be governed by an [IETF-approved RFC][ietf rfc] or a [Google-approved AIP](./0001.md). +### Type References + +Some generic field types (AIP-146), like `google.protobuf.Any`, can still have +a limited set of possible types. Identifying the type(s) of said field can be +done with the `google.api.TypeReference` via the +`google.api.FieldInfo.referenced_types` field, like so: + +```proto +message ModelResponse { + google.protobuf.Any raw_response = 1 [(google.api.field_info) = { + referenced_types: {type_name: "google.library.v1.TitleGenerationResponse"} + referenced_types: {type_name: "google.library.v1.ChapterGenerationResponse"} + referenced_types: {type_name: "google.library.v1.SummaryGenerationResponse"} + }]; +} +``` + +Currently, the field **must** be of type `google.protobuf.Any`. + +#### Type Reference Compatibility + +Adding a new type reference to an existing field is **backwards compatible**, so +long as it matches what the field has always contained. + +Changing a type reference in place or removing a possible type is +**not backwards compatible**, and should be considered a breaking change. + ## Rationale #### Why add a format specifier? @@ -112,6 +139,17 @@ and see usage in Google APIs. Requiring such extra guidance means that governing the format specification is not the responsibility of the `FieldInfo.Format` enumeration itself. +#### Why annotate type reference on generic-typed fields? + +Without this statically defined type information, tools consuming the API +specification have no indicator of the types that the generic field could +contain, limiting their ability to facilitate accurate API consumption. See +[AIP-146 Declaring `Any` type references][generics] for more specific rationale. + +## Changelog + +- **2024-04-18:** Add Type References section for new `referenced_types` field. + [field info proto]: https://github.com/googleapis/googleapis/blob/master/google/api/field_info.proto [rfc 4122]: https://datatracker.ietf.org/doc/html/rfc4122 [rfc 791]: https://datatracker.ietf.org/doc/html/rfc791 @@ -119,3 +157,4 @@ enumeration itself. [rfc 5952]: https://datatracker.ietf.org/doc/html/rfc5952 [ietf rfc]: https://www.ietf.org/standards/rfcs [java uuid]: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html +[generics]: ./0146.md#declaring-any-type-references From 44b39b07d3e7a1e13fd3fda3ef5c408d90e74882 Mon Sep 17 00:00:00 2001 From: noahdietz Date: Fri, 19 Apr 2024 09:26:42 -0700 Subject: [PATCH 2/5] add wildcard typeref --- aip/general/0146.md | 3 +-- aip/general/0202.md | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/aip/general/0146.md b/aip/general/0146.md index 4545e8c5f1..ab8d8153cc 100644 --- a/aip/general/0146.md +++ b/aip/general/0146.md @@ -88,8 +88,7 @@ which is an often-unfamiliar process. Because of this, `Any` **should not** be used unless other options are infeasible. -If an `Any` is used and its set of possible types is controlled by the service, -it **must** be annotated with the type(s) it references. See +If an `Any` is used it **must** be annotated with the type(s) it references. See [AIP-202 Type References][typeref] for more details. ## Rationale diff --git a/aip/general/0202.md b/aip/general/0202.md index 4fa6d0fb74..a180d41bce 100644 --- a/aip/general/0202.md +++ b/aip/general/0202.md @@ -98,7 +98,13 @@ message ModelResponse { } ``` -Currently, the field **must** be of type `google.protobuf.Any`. +If the set of possible types is unknown to the specification author i.e., the +*client* packs the field with its own type, then a single `referenced_types` +entry with `type_name : "*"` can be used. The wildcard value **must not** be +used in conjunction with fully-qualified references. + +Currently, the field annotated with `referenced_types` **must** be of type +`google.protobuf.Any`. #### Type Reference Compatibility @@ -146,6 +152,13 @@ specification have no indicator of the types that the generic field could contain, limiting their ability to facilitate accurate API consumption. See [AIP-146 Declaring `Any` type references][generics] for more specific rationale. +#### Why support a wildcard value for type references? + +Generic fields can be used to accept generic user input, in which case, the +specification author/service implementor would not be able to statically define +the list of possible types the generic field could contain. The wildcard value +explicitly states this relationship to consumers, tools, etc.. + ## Changelog - **2024-04-18:** Add Type References section for new `referenced_types` field. From a927d4c4d2ca814f43dae15b3a7d486f6c50879d Mon Sep 17 00:00:00 2001 From: noahdietz Date: Tue, 23 Apr 2024 09:21:49 -0700 Subject: [PATCH 3/5] address feedback --- aip/general/0202.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/aip/general/0202.md b/aip/general/0202.md index a180d41bce..31a6239c01 100644 --- a/aip/general/0202.md +++ b/aip/general/0202.md @@ -98,7 +98,7 @@ message ModelResponse { } ``` -If the set of possible types is unknown to the specification author i.e., the +If the set of possible types is unknown to the specification author, e.g. the *client* packs the field with its own type, then a single `referenced_types` entry with `type_name : "*"` can be used. The wildcard value **must not** be used in conjunction with fully-qualified references. @@ -154,10 +154,13 @@ contain, limiting their ability to facilitate accurate API consumption. See #### Why support a wildcard value for type references? -Generic fields can be used to accept generic user input, in which case, the -specification author/service implementor would not be able to statically define -the list of possible types the generic field could contain. The wildcard value -explicitly states this relationship to consumers, tools, etc.. +There are cases where the set of possible types for a generic field is not known +to the author/service implementor. For example, when a generic is used as part +of a shared interface, like a platform logging framework, or when it is used to +accept generic user input. In these cases, the wildcard value explicitly states +the ambiguous nature of the field to consumers, tools, etc. to be handled +accorindgly. Without it, the alternative is simply not annotating a generic +field, which conveys nothing. ## Changelog From 0f2c49317cbb57e2fb9b3eb2b7d73500f1b29f6b Mon Sep 17 00:00:00 2001 From: Noah Dietz Date: Mon, 19 Aug 2024 16:14:43 -0700 Subject: [PATCH 4/5] chore(AIP-146): update changelog entry date --- aip/general/0146.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aip/general/0146.md b/aip/general/0146.md index ab8d8153cc..67c70fda94 100644 --- a/aip/general/0146.md +++ b/aip/general/0146.md @@ -105,7 +105,7 @@ annotation is necessary to forward declare what an `Any` could contain. ## Changelog -- **2024-04-18:** Add `Any` type reference requirement and rationale. +- **2024-08-19:** Add `Any` type reference requirement and rationale. [any]: https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf/any.proto From 2e34035635436a7e9dd2429a7bd23747e3d95f0c Mon Sep 17 00:00:00 2001 From: Noah Dietz Date: Mon, 19 Aug 2024 16:15:06 -0700 Subject: [PATCH 5/5] chore(AIP-202): update changelog entry date --- aip/general/0202.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aip/general/0202.md b/aip/general/0202.md index 31a6239c01..462cc618af 100644 --- a/aip/general/0202.md +++ b/aip/general/0202.md @@ -164,7 +164,7 @@ field, which conveys nothing. ## Changelog -- **2024-04-18:** Add Type References section for new `referenced_types` field. +- **2024-08-19:** Add Type References section for new `referenced_types` field. [field info proto]: https://github.com/googleapis/googleapis/blob/master/google/api/field_info.proto [rfc 4122]: https://datatracker.ietf.org/doc/html/rfc4122