Repository: crossplane/crossplane

Issue:
Support optionally caching a `RunFunctionResponse`
<!--
Thank you for helping to improve Crossplane!

Please be sure to search for open issues before raising a new one. We use issues
for bug reports and feature requests. Please find us at https://slack.crossplane.io
for questions, support, and discussion.
-->

### What problem are you facing?
<!--
Please tell us a little about your use case - it's okay if it's hypothetical!
Leading with this context helps frame the feature request so we can ensure we
implement it sensibly.
--->
Currently the `FunctionComposer` will call every Function in the pipeline on every reconcile. Ideally we'd allow Functions to opt-in to having their response cached, so that we can avoid calling a Function too frequently. This is especially relevant for deterministic Functions that will always return the same result given a particular input.

### How could Crossplane help solve your problem?
<!--
Let us know how you think Crossplane could help with your use case. 
-->
The RunFunction RPCs already have some affordance for this per [the design](https://github.com/crossplane/crossplane/blob/e3c8e1c1dacf9016f0e4cdd1409303dfaef7608b/design/design-doc-composition-functions.md):

* `RunFunctionRequest` includes a `meta.tag` field which should opaquely identify the request.
* `RunFunctionResponse` includes the `meta.tag` from the request, and a `meta.ttl` indicating how long the response is valid.

I believe we could use https://github.com/cerbos/protoc-gen-go-hashpb to generate the `meta.tag`, and cache responses by tag until their TTL expires. We could then do a cache lookup by tag before sending a request to see if we already have a cached response.

Discussion:
@negz: Adding to the v1.15 milestone - I don't think this needs to be in-scope for Functions to hit beta.@negz: I'm not sure this needs to be in-scope for functions to hit GA either. Once realtime compositions are beta (https://github.com/crossplane/crossplane/issues/4828) there will be a lot less need for caching function responses, since we'll only call functions when something actually changes (modulo requeues, etc).

I think we should focus on observability and scale testing first before building caching. We may find that we don't need it.@github-actions: Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as `stale` because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment **starting with** `/fresh` will mark this issue as not stale.@bobh66: /fresh@phisco: /fresh@github-actions: Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as `stale` because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment **starting with** `/fresh` will mark this issue as not stale.@negz: /fresh@github-actions: Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as `stale` because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment **starting with** `/fresh` will mark this issue as not stale.

Solution patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 131e53833..28a81b494 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,7 +8,7 @@ on:
       # TODO(negz): Remove this and all references to the v2 branches below
       # if/when v2 is merged into main. It's a temporary branch for v2 preview
       # development.
-      - v2 
+      - v2
   pull_request: {}
   workflow_dispatch: {}
 
@@ -229,6 +229,7 @@ jobs:
           - base
           - package-dependency-updates
           - package-signature-verification
+          - function-response-cache
 
     steps:
       - name: Checkout
@@ -299,6 +300,13 @@ jobs:
           secret: ${{ secrets.BUILDPULSE_SECRET_ACCESS_KEY }}
           path: _output/tests/e2e-tests.xml
 
+      - name: Upload E2E Test Artifacts to GitHub
+        if: '!cancelled()'
+        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
+        with:
+          name: e2e-tests-${{ matrix.test-suite }}
+          path: _output/tests/**
+
   publish-artifacts:
     runs-on: ubuntu-22.04
 
@@ -433,5 +441,4 @@ jobs:
         with:
           token: ${{ secrets.BUF_TOKEN }}
           pr_comment: false
-          input: apis
 
diff --git a/Earthfile b/Earthfile
index d35883250..d41301022 100644
--- a/Earthfile
+++ b/Earthfile
@@ -74,13 +74,16 @@ e2e:
       # https://github.com/earthly/earthly/issues/4143 is fixed.
       RUN gotestsum \
         --rerun-fails \
-      	--no-color=false \
-	--format ${GOTESTSUM_FORMAT} \
-	--junitfile e2e-tests.xml \
-	--raw-command go tool test2json -t -p E2E ./e2e -test.v ${FLAGS}
+        --rerun-fails-report e2e-rerun-fails.txt \
+        --hide-summary output \ # See https://github.com/gotestyourself/gotestsum/issues/423
+        --no-color=false \
+        --format ${GOTESTSUM_FORMAT} \
+        --junitfile e2e-tests.xml \
+        --raw-command go tool test2json -t -p E2E ./e2e -test.v ${FLAGS}
     END
   FINALLY
     SAVE ARTIFACT --if-exists e2e-tests.xml AS LOCAL _output/tests/e2e-tests.xml
+    SAVE ARTIFACT --if-exists e2e-rerun-fails.txt AS LOCAL _output/tests/e2e-rerun-fails.txt
   END
 
 # hack builds Crossplane, and deploys it to a kind cluster. It runs in your
@@ -135,6 +138,7 @@ go-modules:
 go-modules-tidy:
   FROM +go-modules
   CACHE --id go-build --sharing shared /root/.cache/go-build
+  COPY generate.go .
   COPY --dir apis/ cmd/ internal/ pkg/ test/ .
   RUN go mod tidy
   RUN go mod verify
@@ -146,9 +150,10 @@ go-generate:
   FROM +go-modules
   CACHE --id go-build --sharing shared /root/.cache/go-build
   COPY +kubectl-setup/kubectl /usr/local/bin/kubectl
+  COPY generate.go buf.yaml buf.gen.yaml .
   COPY --dir cluster/crd-patches cluster/crd-patches
   COPY --dir hack/ apis/ internal/ .
-  RUN go generate -tags 'generate' ./apis/...
+  RUN go generate -tags 'generate' .
   # TODO(negz): Can this move into generate.go? Ideally it would live there with
   # the code that actually generates the CRDs, but it depends on kubectl.
   RUN kubectl patch --local --type=json \
@@ -157,6 +162,7 @@ go-generate:
     --output=yaml > /tmp/patched.yaml \
     && mv /tmp/patched.yaml cluster/crds/pkg.crossplane.io_deploymentruntimeconfigs.yaml
   SAVE ARTIFACT apis/ AS LOCAL apis
+  SAVE ARTIFACT internal/ AS LOCAL internal
   SAVE ARTIFACT cluster/crds AS LOCAL cluster/crds
   SAVE ARTIFACT cluster/meta AS LOCAL cluster/meta
 
diff --git a/apis/apiextensions/fn/proto/v1/run_function.pb.go b/apis/apiextensions/fn/proto/v1/run_function.pb.go
index 91fdd3f5d..87b6fd47d 100644
--- a/apis/apiextensions/fn/proto/v1/run_function.pb.go
+++ b/apis/apiextensions/fn/proto/v1/run_function.pb.go
@@ -17,7 +17,7 @@
 // versions:
 // 	protoc-gen-go v1.35.2
 // 	protoc        (unknown)
-// source: apiextensions/fn/proto/v1/run_function.proto
+// source: apis/apiextensions/fn/proto/v1/run_function.proto
 
 //buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
 
@@ -75,11 +75,11 @@ func (x Ready) String() string {
 }
 
 func (Ready) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[0].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[0].Descriptor()
 }
 
 func (Ready) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[0]
+	return &file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[0]
 }
 
 func (x Ready) Number() protoreflect.EnumNumber {
@@ -88,7 +88,7 @@ func (x Ready) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Ready.Descriptor instead.
 func (Ready) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{0}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{0}
 }
 
 // Severity of Function results.
@@ -136,11 +136,11 @@ func (x Severity) String() string {
 }
 
 func (Severity) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[1].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[1].Descriptor()
 }
 
 func (Severity) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[1]
+	return &file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[1]
 }
 
 func (x Severity) Number() protoreflect.EnumNumber {
@@ -149,7 +149,7 @@ func (x Severity) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Severity.Descriptor instead.
 func (Severity) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{1}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{1}
 }
 
 // Target of Function results and conditions.
@@ -191,11 +191,11 @@ func (x Target) String() string {
 }
 
 func (Target) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[2].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[2].Descriptor()
 }
 
 func (Target) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[2]
+	return &file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[2]
 }
 
 func (x Target) Number() protoreflect.EnumNumber {
@@ -204,7 +204,7 @@ func (x Target) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Target.Descriptor instead.
 func (Target) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{2}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{2}
 }
 
 type Status int32
@@ -243,11 +243,11 @@ func (x Status) String() string {
 }
 
 func (Status) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[3].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[3].Descriptor()
 }
 
 func (Status) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1_run_function_proto_enumTypes[3]
+	return &file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes[3]
 }
 
 func (x Status) Number() protoreflect.EnumNumber {
@@ -256,7 +256,7 @@ func (x Status) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Status.Descriptor instead.
 func (Status) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{3}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{3}
 }
 
 // A RunFunctionRequest requests that the Composition Function be run.
@@ -304,7 +304,7 @@ type RunFunctionRequest struct {
 
 func (x *RunFunctionRequest) Reset() {
 	*x = RunFunctionRequest{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -316,7 +316,7 @@ func (x *RunFunctionRequest) String() string {
 func (*RunFunctionRequest) ProtoMessage() {}
 
 func (x *RunFunctionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -329,7 +329,7 @@ func (x *RunFunctionRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RunFunctionRequest.ProtoReflect.Descriptor instead.
 func (*RunFunctionRequest) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{0}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{0}
 }
 
 func (x *RunFunctionRequest) GetMeta() *RequestMeta {
@@ -397,7 +397,7 @@ type Credentials struct {
 
 func (x *Credentials) Reset() {
 	*x = Credentials{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -409,7 +409,7 @@ func (x *Credentials) String() string {
 func (*Credentials) ProtoMessage() {}
 
 func (x *Credentials) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -422,7 +422,7 @@ func (x *Credentials) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Credentials.ProtoReflect.Descriptor instead.
 func (*Credentials) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{1}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{1}
 }
 
 func (m *Credentials) GetSource() isCredentials_Source {
@@ -461,7 +461,7 @@ type CredentialData struct {
 
 func (x *CredentialData) Reset() {
 	*x = CredentialData{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[2]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[2]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -473,7 +473,7 @@ func (x *CredentialData) String() string {
 func (*CredentialData) ProtoMessage() {}
 
 func (x *CredentialData) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[2]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[2]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -486,7 +486,7 @@ func (x *CredentialData) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use CredentialData.ProtoReflect.Descriptor instead.
 func (*CredentialData) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{2}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{2}
 }
 
 func (x *CredentialData) GetData() map[string][]byte {
@@ -507,7 +507,7 @@ type Resources struct {
 
 func (x *Resources) Reset() {
 	*x = Resources{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[3]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[3]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -519,7 +519,7 @@ func (x *Resources) String() string {
 func (*Resources) ProtoMessage() {}
 
 func (x *Resources) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[3]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[3]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -532,7 +532,7 @@ func (x *Resources) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Resources.ProtoReflect.Descriptor instead.
 func (*Resources) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{3}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{3}
 }
 
 func (x *Resources) GetItems() []*Resource {
@@ -576,7 +576,7 @@ type RunFunctionResponse struct {
 
 func (x *RunFunctionResponse) Reset() {
 	*x = RunFunctionResponse{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -588,7 +588,7 @@ func (x *RunFunctionResponse) String() string {
 func (*RunFunctionResponse) ProtoMessage() {}
 
 func (x *RunFunctionResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -601,7 +601,7 @@ func (x *RunFunctionResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RunFunctionResponse.ProtoReflect.Descriptor instead.
 func (*RunFunctionResponse) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{4}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *RunFunctionResponse) GetMeta() *ResponseMeta {
@@ -652,14 +652,14 @@ type RequestMeta struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	// An opaque string identifying the content of the request. Two identical
-	// requests should have the same tag.
+	// An opaque string identifying a request. Requests with identical tags will
+	// be otherwise identical.
 	Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
 }
 
 func (x *RequestMeta) Reset() {
 	*x = RequestMeta{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[5]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[5]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -671,7 +671,7 @@ func (x *RequestMeta) String() string {
 func (*RequestMeta) ProtoMessage() {}
 
 func (x *RequestMeta) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[5]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[5]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -684,7 +684,7 @@ func (x *RequestMeta) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RequestMeta.ProtoReflect.Descriptor instead.
 func (*RequestMeta) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{5}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *RequestMeta) GetTag() string {
@@ -707,7 +707,7 @@ type Requirements struct {
 
 func (x *Requirements) Reset() {
 	*x = Requirements{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[6]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[6]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -719,7 +719,7 @@ func (x *Requirements) String() string {
 func (*Requirements) ProtoMessage() {}
 
 func (x *Requirements) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[6]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[6]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -732,7 +732,7 @@ func (x *Requirements) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Requirements.ProtoReflect.Descriptor instead.
 func (*Requirements) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{6}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *Requirements) GetExtraResources() map[string]*ResourceSelector {
@@ -763,7 +763,7 @@ type ResourceSelector struct {
 
 func (x *ResourceSelector) Reset() {
 	*x = ResourceSelector{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -775,7 +775,7 @@ func (x *ResourceSelector) String() string {
 func (*ResourceSelector) ProtoMessage() {}
 
 func (x *ResourceSelector) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -788,7 +788,7 @@ func (x *ResourceSelector) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ResourceSelector.ProtoReflect.Descriptor instead.
 func (*ResourceSelector) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{7}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *ResourceSelector) GetApiVersion() string {
@@ -855,7 +855,7 @@ type MatchLabels struct {
 
 func (x *MatchLabels) Reset() {
 	*x = MatchLabels{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[8]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[8]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -867,7 +867,7 @@ func (x *MatchLabels) String() string {
 func (*MatchLabels) ProtoMessage() {}
 
 func (x *MatchLabels) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[8]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[8]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -880,7 +880,7 @@ func (x *MatchLabels) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use MatchLabels.ProtoReflect.Descriptor instead.
 func (*MatchLabels) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{8}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *MatchLabels) GetLabels() map[string]string {
@@ -907,7 +907,7 @@ type ResponseMeta struct {
 
 func (x *ResponseMeta) Reset() {
 	*x = ResponseMeta{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -919,7 +919,7 @@ func (x *ResponseMeta) String() string {
 func (*ResponseMeta) ProtoMessage() {}
 
 func (x *ResponseMeta) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -932,7 +932,7 @@ func (x *ResponseMeta) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ResponseMeta.ProtoReflect.Descriptor instead.
 func (*ResponseMeta) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{9}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *ResponseMeta) GetTag() string {
@@ -963,7 +963,7 @@ type State struct {
 
 func (x *State) Reset() {
 	*x = State{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[10]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[10]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -975,7 +975,7 @@ func (x *State) String() string {
 func (*State) ProtoMessage() {}
 
 func (x *State) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[10]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[10]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -988,7 +988,7 @@ func (x *State) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use State.ProtoReflect.Descriptor instead.
 func (*State) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{10}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *State) GetComposite() *Resource {
@@ -1056,7 +1056,7 @@ type Resource struct {
 
 func (x *Resource) Reset() {
 	*x = Resource{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[11]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[11]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1068,7 +1068,7 @@ func (x *Resource) String() string {
 func (*Resource) ProtoMessage() {}
 
 func (x *Resource) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[11]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[11]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1081,7 +1081,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Resource.ProtoReflect.Descriptor instead.
 func (*Resource) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{11}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *Resource) GetResource() *structpb.Struct {
@@ -1124,7 +1124,7 @@ type Result struct {
 
 func (x *Result) Reset() {
 	*x = Result{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1136,7 +1136,7 @@ func (x *Result) String() string {
 func (*Result) ProtoMessage() {}
 
 func (x *Result) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1149,7 +1149,7 @@ func (x *Result) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Result.ProtoReflect.Descriptor instead.
 func (*Result) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{12}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *Result) GetSeverity() Severity {
@@ -1208,7 +1208,7 @@ type Condition struct {
 
 func (x *Condition) Reset() {
 	*x = Condition{}
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1220,7 +1220,7 @@ func (x *Condition) String() string {
 func (*Condition) ProtoMessage() {}
 
 func (x *Condition) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13]
+	mi := &file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1233,7 +1233,7 @@ func (x *Condition) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Condition.ProtoReflect.Descriptor instead.
 func (*Condition) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{13}
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *Condition) GetType() string {
@@ -1271,273 +1271,273 @@ func (x *Condition) GetTarget() Target {
 	return Target_TARGET_UNSPECIFIED
 }
 
-var File_apiextensions_fn_proto_v1_run_function_proto protoreflect.FileDescriptor
-
-var file_apiextensions_fn_proto_v1_run_function_proto_rawDesc = []byte{
-	0x0a, 0x2c, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x75, 0x6e, 0x5f,
-	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19,
-	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63,
-	0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x05, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x46,
-	0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a,
-	0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61,
-	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x62,
-	0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61,
-	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08,
-	0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x69,
-	0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x65,
-	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x64, 0x65, 0x73,
-	0x69, 0x72, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05,
-	0x69, 0x6e, 0x70, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74,
-	0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75,
-	0x63, 0x74, 0x48, 0x01, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x88, 0x01, 0x01,
-	0x12, 0x6a, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
-	0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x61, 0x70, 0x69, 0x65,
-	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-	0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78,
-	0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x0b,
-	0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x3e, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75,
-	0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x1a, 0x67,
-	0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
+var File_apis_apiextensions_fn_proto_v1_run_function_proto protoreflect.FileDescriptor
+
+var file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDesc = []byte{
+	0x0a, 0x31, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31,
+	0x2f, 0x72, 0x75, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x12, 0x19, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x1a, 0x1e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
+	0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
+	0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x05, 0x0a,
+	0x12, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12,
+	0x3c, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74,
+	0x61, 0x74, 0x65, 0x52, 0x08, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x3a, 0x0a,
+	0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
+	0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
+	0x52, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70,
+	0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63,
+	0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a,
+	0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+	0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x01, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+	0x78, 0x74, 0x88, 0x01, 0x01, 0x12, 0x6a, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72,
+	0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41,
+	0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75,
+	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x78,
+	0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x73, 0x12, 0x60, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
+	0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
 	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x66, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x64, 0x65,
-	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
-	0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61,
+	0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
+	0x61, 0x6c, 0x73, 0x1a, 0x67, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70,
+	0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x66, 0x0a, 0x10,
+	0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+	0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
+	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x0a,
+	0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x6d, 0x0a, 0x0b, 0x43, 0x72,
+	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x63, 0x72, 0x65,
+	0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43,
+	0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52,
+	0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x42,
+	0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x0e, 0x43, 0x72,
+	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x04,
+	0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
+	0x6c, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
+	0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74,
+	0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46,
+	0x0a, 0x09, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x69,
+	0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
+	0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xa2, 0x03, 0x0a, 0x13, 0x52, 0x75, 0x6e, 0x46, 0x75,
+	0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b,
+	0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61,
 	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x61, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42,
-	0x08, 0x0a, 0x06, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f,
-	0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x6d, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x61, 0x6c, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
-	0x61, 0x6c, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x3a, 0x0a, 0x07, 0x64,
+	0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07,
+	0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c,
+	0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73,
+	0x75, 0x6c, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00,
+	0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x88, 0x01, 0x01, 0x12, 0x4b, 0x0a, 0x0c,
+	0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52,
+	0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x71,
+	0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6e,
+	0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
 	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e,
-	0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64,
-	0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
-	0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61,
-	0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
-	0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
-	0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
-	0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46, 0x0a, 0x09, 0x52, 0x65, 0x73,
-	0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18,
-	0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d,
-	0x73, 0x22, 0xa2, 0x03, 0x0a, 0x13, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
-	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x6d, 0x65, 0x74,
-	0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
-	0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x3a, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65,
-	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42,
+	0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
+	0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xe4, 0x01, 0x0a,
+	0x0c, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x64, 0x0a,
+	0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+	0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
+	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e,
+	0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e,
+	0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x1a, 0x6e, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70,
+	0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
+	0x02, 0x38, 0x01, 0x22, 0xbe, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f,
+	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61,
+	0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e,
+	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a,
+	0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x48, 0x00, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b,
+	0x0a, 0x0c, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0b,
+	0x6d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x6d,
+	0x61, 0x74, 0x63, 0x68, 0x22, 0x94, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61,
+	0x62, 0x65, 0x6c, 0x73, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x2e, 0x4c, 0x61, 0x62,
+	0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73,
+	0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+	0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+	0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x0c, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74,
+	0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a,
+	0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01, 0x42,
+	0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74,
+	0x65, 0x12, 0x41, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+	0x73, 0x69, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
 	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72,
-	0x65, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e,
-	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12,
-	0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e,
-	0x74, 0x65, 0x78, 0x74, 0x88, 0x01, 0x01, 0x12, 0x4b, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69,
-	0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
-	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72,
-	0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
-	0x65, 0x6e, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
-	0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
-	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a,
-	0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63,
-	0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xe4, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75,
-	0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72,
-	0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x3b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
-	0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61,
-	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e,
-	0x65, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x6e,
-	0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
 	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
 	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63,
-	0x74, 0x6f, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe,
-	0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63,
-	0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63,
-	0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09,
-	0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x6d, 0x61, 0x74,
-	0x63, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63,
-	0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x63, 0x68,
-	0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x22,
-	0x94, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12,
-	0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x32, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63,
-	0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c,
-	0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
-	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x48, 0x00, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74,
-	0x74, 0x6c, 0x22, 0xfc, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x41, 0x0a, 0x09,
-	0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x23, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x12,
-	0x4d, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
-	0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
-	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53,
-	0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x61,
-	0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
-	0x01, 0x22, 0xa8, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33,
-	0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
-	0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x3a, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44,
-	0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e,
-	0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x36,
-	0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e,
-	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52,
-	0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+	0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa8, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75,
+	0x72, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08,
+	0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e,
+	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
 	0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd6, 0x01, 0x0a,
-	0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3f, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72,
-	0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x65,
-	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08,
-	0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12,
-	0x3e, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x21, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67,
-	0x65, 0x74, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42,
-	0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74,
-	0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xe8, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74,
-	0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
-	0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
-	0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x06, 0x74, 0x61, 0x72,
-	0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x65,
-	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x01, 0x52, 0x06,
-	0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65,
-	0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
-	0x2a, 0x3f, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x41,
-	0x44, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
-	0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01,
-	0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10,
-	0x02, 0x2a, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a,
-	0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
-	0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52,
-	0x49, 0x54, 0x59, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53,
-	0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10,
-	0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f,
-	0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
-	0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
-	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47,
-	0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x1e,
-	0x0a, 0x1a, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49,
-	0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x02, 0x2a, 0x7f,
-	0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x54, 0x41, 0x54,
-	0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53,
-	0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54,
-	0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55,
-	0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54,
-	0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x55,
-	0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f,
-	0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x03, 0x32,
-	0x87, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x6e,
-	0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x52, 0x75, 0x6e,
-	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
-	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74,
-	0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61,
-	0x6e, 0x65, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70,
-	0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
-	0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
+	0x52, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61,
+	0x69, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x0e, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52,
+	0x65, 0x61, 0x64, 0x79, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a, 0x16, 0x43,
+	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x22, 0xd6, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3f, 0x0a, 0x08,
+	0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23,
+	0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72,
+	0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a,
+	0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
+	0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
+	0x6e, 0x88, 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
+	0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42,
+	0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xe8, 0x01, 0x0a, 0x09, 0x43,
+	0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x06,
+	0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
+	0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
+	0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12,
+	0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+	0x48, 0x00, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x3e,
+	0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21,
+	0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65,
+	0x74, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0a,
+	0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74,
+	0x61, 0x72, 0x67, 0x65, 0x74, 0x2a, 0x3f, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x15,
+	0x0a, 0x11, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54,
+	0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x46,
+	0x41, 0x4c, 0x53, 0x45, 0x10, 0x02, 0x2a, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69,
+	0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55,
+	0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e,
+	0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01,
+	0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52,
+	0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49,
+	0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x06, 0x54,
+	0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f,
+	0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a,
+	0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54,
+	0x45, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f,
+	0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x41, 0x49,
+	0x4d, 0x10, 0x02, 0x2a, 0x7f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a,
+	0x1c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f,
+	0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+	0x1c, 0x0a, 0x18, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54,
+	0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a,
+	0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f,
+	0x4e, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x41, 0x54,
+	0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x4c,
+	0x53, 0x45, 0x10, 0x03, 0x32, 0x87, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6e,
+	0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e,
+	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x41,
+	0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f,
+	0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61,
+	0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76,
+	0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
-	file_apiextensions_fn_proto_v1_run_function_proto_rawDescOnce sync.Once
-	file_apiextensions_fn_proto_v1_run_function_proto_rawDescData = file_apiextensions_fn_proto_v1_run_function_proto_rawDesc
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescOnce sync.Once
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescData = file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDesc
 )
 
-func file_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP() []byte {
-	file_apiextensions_fn_proto_v1_run_function_proto_rawDescOnce.Do(func() {
-		file_apiextensions_fn_proto_v1_run_function_proto_rawDescData = protoimpl.X.CompressGZIP(file_apiextensions_fn_proto_v1_run_function_proto_rawDescData)
+func file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescGZIP() []byte {
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescOnce.Do(func() {
+		file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescData = protoimpl.X.CompressGZIP(file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescData)
 	})
-	return file_apiextensions_fn_proto_v1_run_function_proto_rawDescData
+	return file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDescData
 }
 
-var file_apiextensions_fn_proto_v1_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
-var file_apiextensions_fn_proto_v1_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
-var file_apiextensions_fn_proto_v1_run_function_proto_goTypes = []any{
+var file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
+var file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_apis_apiextensions_fn_proto_v1_run_function_proto_goTypes = []any{
 	(Ready)(0),                  // 0: apiextensions.fn.proto.v1.Ready
 	(Severity)(0),               // 1: apiextensions.fn.proto.v1.Severity
 	(Target)(0),                 // 2: apiextensions.fn.proto.v1.Target
@@ -1566,7 +1566,7 @@ var file_apiextensions_fn_proto_v1_run_function_proto_goTypes = []any{
 	(*structpb.Struct)(nil),     // 25: google.protobuf.Struct
 	(*durationpb.Duration)(nil), // 26: google.protobuf.Duration
 }
-var file_apiextensions_fn_proto_v1_run_function_proto_depIdxs = []int32{
+var file_apis_apiextensions_fn_proto_v1_run_function_proto_depIdxs = []int32{
 	9,  // 0: apiextensions.fn.proto.v1.RunFunctionRequest.meta:type_name -> apiextensions.fn.proto.v1.RequestMeta
 	14, // 1: apiextensions.fn.proto.v1.RunFunctionRequest.observed:type_name -> apiextensions.fn.proto.v1.State
 	14, // 2: apiextensions.fn.proto.v1.RunFunctionRequest.desired:type_name -> apiextensions.fn.proto.v1.State
@@ -1609,40 +1609,40 @@ var file_apiextensions_fn_proto_v1_run_function_proto_depIdxs = []int32{
 	0,  // [0:33] is the sub-list for field type_name
 }
 
-func init() { file_apiextensions_fn_proto_v1_run_function_proto_init() }
-func file_apiextensions_fn_proto_v1_run_function_proto_init() {
-	if File_apiextensions_fn_proto_v1_run_function_proto != nil {
+func init() { file_apis_apiextensions_fn_proto_v1_run_function_proto_init() }
+func file_apis_apiextensions_fn_proto_v1_run_function_proto_init() {
+	if File_apis_apiextensions_fn_proto_v1_run_function_proto != nil {
 		return
 	}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1].OneofWrappers = []any{
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[0].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[1].OneofWrappers = []any{
 		(*Credentials_CredentialData)(nil),
 	}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7].OneofWrappers = []any{
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[4].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[7].OneofWrappers = []any{
 		(*ResourceSelector_MatchName)(nil),
 		(*ResourceSelector_MatchLabels)(nil),
 	}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[9].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[12].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes[13].OneofWrappers = []any{}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_apiextensions_fn_proto_v1_run_function_proto_rawDesc,
+			RawDescriptor: file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDesc,
 			NumEnums:      4,
 			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
-		GoTypes:           file_apiextensions_fn_proto_v1_run_function_proto_goTypes,
-		DependencyIndexes: file_apiextensions_fn_proto_v1_run_function_proto_depIdxs,
-		EnumInfos:         file_apiextensions_fn_proto_v1_run_function_proto_enumTypes,
-		MessageInfos:      file_apiextensions_fn_proto_v1_run_function_proto_msgTypes,
+		GoTypes:           file_apis_apiextensions_fn_proto_v1_run_function_proto_goTypes,
+		DependencyIndexes: file_apis_apiextensions_fn_proto_v1_run_function_proto_depIdxs,
+		EnumInfos:         file_apis_apiextensions_fn_proto_v1_run_function_proto_enumTypes,
+		MessageInfos:      file_apis_apiextensions_fn_proto_v1_run_function_proto_msgTypes,
 	}.Build()
-	File_apiextensions_fn_proto_v1_run_function_proto = out.File
-	file_apiextensions_fn_proto_v1_run_function_proto_rawDesc = nil
-	file_apiextensions_fn_proto_v1_run_function_proto_goTypes = nil
-	file_apiextensions_fn_proto_v1_run_function_proto_depIdxs = nil
+	File_apis_apiextensions_fn_proto_v1_run_function_proto = out.File
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_rawDesc = nil
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_goTypes = nil
+	file_apis_apiextensions_fn_proto_v1_run_function_proto_depIdxs = nil
 }
diff --git a/apis/apiextensions/fn/proto/v1/run_function.proto b/apis/apiextensions/fn/proto/v1/run_function.proto
index 2a4d0483b..d4a38a9e7 100644
--- a/apis/apiextensions/fn/proto/v1/run_function.proto
+++ b/apis/apiextensions/fn/proto/v1/run_function.proto
@@ -130,8 +130,8 @@ message RunFunctionResponse {
 
 // RequestMeta contains metadata pertaining to a RunFunctionRequest.
 message RequestMeta {
-  // An opaque string identifying the content of the request. Two identical
-  // requests should have the same tag.
+  // An opaque string identifying a request. Requests with identical tags will
+  // be otherwise identical.
   string tag = 1;
 }
 
diff --git a/apis/apiextensions/fn/proto/v1/run_function_grpc.pb.go b/apis/apiextensions/fn/proto/v1/run_function_grpc.pb.go
index 15e483f88..15abac6ab 100644
--- a/apis/apiextensions/fn/proto/v1/run_function_grpc.pb.go
+++ b/apis/apiextensions/fn/proto/v1/run_function_grpc.pb.go
@@ -17,7 +17,7 @@
 // versions:
 // - protoc-gen-go-grpc v1.3.0
 // - protoc             (unknown)
-// source: apiextensions/fn/proto/v1/run_function.proto
+// source: apis/apiextensions/fn/proto/v1/run_function.proto
 
 //buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
 
@@ -124,5 +124,5 @@ var FunctionRunnerService_ServiceDesc = grpc.ServiceDesc{
 		},
 	},
 	Streams:  []grpc.StreamDesc{},
-	Metadata: "apiextensions/fn/proto/v1/run_function.proto",
+	Metadata: "apis/apiextensions/fn/proto/v1/run_function.proto",
 }
diff --git a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.pb.go b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.pb.go
index 9e49d9602..8135423f3 100644
--- a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.pb.go
+++ b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.pb.go
@@ -13,13 +13,13 @@
 //See the License for the specific language governing permissions and
 //limitations under the License.
 
-// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/fn/proto/v1/run_function.proto by ./hack/duplicate_proto_type.sh. DO NOT EDIT.
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.35.2
 // 	protoc        (unknown)
-// source: apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
+// source: apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
 
 //buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
 
@@ -77,11 +77,11 @@ func (x Ready) String() string {
 }
 
 func (Ready) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[0].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[0].Descriptor()
 }
 
 func (Ready) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[0]
+	return &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[0]
 }
 
 func (x Ready) Number() protoreflect.EnumNumber {
@@ -90,7 +90,7 @@ func (x Ready) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Ready.Descriptor instead.
 func (Ready) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{0}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{0}
 }
 
 // Severity of Function results.
@@ -138,11 +138,11 @@ func (x Severity) String() string {
 }
 
 func (Severity) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[1].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[1].Descriptor()
 }
 
 func (Severity) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[1]
+	return &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[1]
 }
 
 func (x Severity) Number() protoreflect.EnumNumber {
@@ -151,7 +151,7 @@ func (x Severity) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Severity.Descriptor instead.
 func (Severity) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{1}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{1}
 }
 
 // Target of Function results and conditions.
@@ -193,11 +193,11 @@ func (x Target) String() string {
 }
 
 func (Target) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[2].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[2].Descriptor()
 }
 
 func (Target) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[2]
+	return &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[2]
 }
 
 func (x Target) Number() protoreflect.EnumNumber {
@@ -206,7 +206,7 @@ func (x Target) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Target.Descriptor instead.
 func (Target) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{2}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{2}
 }
 
 type Status int32
@@ -245,11 +245,11 @@ func (x Status) String() string {
 }
 
 func (Status) Descriptor() protoreflect.EnumDescriptor {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[3].Descriptor()
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[3].Descriptor()
 }
 
 func (Status) Type() protoreflect.EnumType {
-	return &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[3]
+	return &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes[3]
 }
 
 func (x Status) Number() protoreflect.EnumNumber {
@@ -258,7 +258,7 @@ func (x Status) Number() protoreflect.EnumNumber {
 
 // Deprecated: Use Status.Descriptor instead.
 func (Status) EnumDescriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{3}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{3}
 }
 
 // A RunFunctionRequest requests that the Composition Function be run.
@@ -306,7 +306,7 @@ type RunFunctionRequest struct {
 
 func (x *RunFunctionRequest) Reset() {
 	*x = RunFunctionRequest{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -318,7 +318,7 @@ func (x *RunFunctionRequest) String() string {
 func (*RunFunctionRequest) ProtoMessage() {}
 
 func (x *RunFunctionRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -331,7 +331,7 @@ func (x *RunFunctionRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RunFunctionRequest.ProtoReflect.Descriptor instead.
 func (*RunFunctionRequest) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{0}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{0}
 }
 
 func (x *RunFunctionRequest) GetMeta() *RequestMeta {
@@ -399,7 +399,7 @@ type Credentials struct {
 
 func (x *Credentials) Reset() {
 	*x = Credentials{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -411,7 +411,7 @@ func (x *Credentials) String() string {
 func (*Credentials) ProtoMessage() {}
 
 func (x *Credentials) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -424,7 +424,7 @@ func (x *Credentials) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Credentials.ProtoReflect.Descriptor instead.
 func (*Credentials) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{1}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{1}
 }
 
 func (m *Credentials) GetSource() isCredentials_Source {
@@ -463,7 +463,7 @@ type CredentialData struct {
 
 func (x *CredentialData) Reset() {
 	*x = CredentialData{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[2]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[2]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -475,7 +475,7 @@ func (x *CredentialData) String() string {
 func (*CredentialData) ProtoMessage() {}
 
 func (x *CredentialData) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[2]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[2]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -488,7 +488,7 @@ func (x *CredentialData) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use CredentialData.ProtoReflect.Descriptor instead.
 func (*CredentialData) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{2}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{2}
 }
 
 func (x *CredentialData) GetData() map[string][]byte {
@@ -509,7 +509,7 @@ type Resources struct {
 
 func (x *Resources) Reset() {
 	*x = Resources{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[3]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[3]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -521,7 +521,7 @@ func (x *Resources) String() string {
 func (*Resources) ProtoMessage() {}
 
 func (x *Resources) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[3]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[3]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -534,7 +534,7 @@ func (x *Resources) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Resources.ProtoReflect.Descriptor instead.
 func (*Resources) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{3}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{3}
 }
 
 func (x *Resources) GetItems() []*Resource {
@@ -578,7 +578,7 @@ type RunFunctionResponse struct {
 
 func (x *RunFunctionResponse) Reset() {
 	*x = RunFunctionResponse{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -590,7 +590,7 @@ func (x *RunFunctionResponse) String() string {
 func (*RunFunctionResponse) ProtoMessage() {}
 
 func (x *RunFunctionResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -603,7 +603,7 @@ func (x *RunFunctionResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RunFunctionResponse.ProtoReflect.Descriptor instead.
 func (*RunFunctionResponse) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{4}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *RunFunctionResponse) GetMeta() *ResponseMeta {
@@ -654,14 +654,14 @@ type RequestMeta struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	// An opaque string identifying the content of the request. Two identical
-	// requests should have the same tag.
+	// An opaque string identifying a request. Requests with identical tags will
+	// be otherwise identical.
 	Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
 }
 
 func (x *RequestMeta) Reset() {
 	*x = RequestMeta{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[5]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[5]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -673,7 +673,7 @@ func (x *RequestMeta) String() string {
 func (*RequestMeta) ProtoMessage() {}
 
 func (x *RequestMeta) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[5]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[5]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -686,7 +686,7 @@ func (x *RequestMeta) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RequestMeta.ProtoReflect.Descriptor instead.
 func (*RequestMeta) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{5}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *RequestMeta) GetTag() string {
@@ -709,7 +709,7 @@ type Requirements struct {
 
 func (x *Requirements) Reset() {
 	*x = Requirements{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[6]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[6]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -721,7 +721,7 @@ func (x *Requirements) String() string {
 func (*Requirements) ProtoMessage() {}
 
 func (x *Requirements) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[6]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[6]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -734,7 +734,7 @@ func (x *Requirements) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Requirements.ProtoReflect.Descriptor instead.
 func (*Requirements) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{6}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *Requirements) GetExtraResources() map[string]*ResourceSelector {
@@ -765,7 +765,7 @@ type ResourceSelector struct {
 
 func (x *ResourceSelector) Reset() {
 	*x = ResourceSelector{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -777,7 +777,7 @@ func (x *ResourceSelector) String() string {
 func (*ResourceSelector) ProtoMessage() {}
 
 func (x *ResourceSelector) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -790,7 +790,7 @@ func (x *ResourceSelector) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ResourceSelector.ProtoReflect.Descriptor instead.
 func (*ResourceSelector) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{7}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *ResourceSelector) GetApiVersion() string {
@@ -857,7 +857,7 @@ type MatchLabels struct {
 
 func (x *MatchLabels) Reset() {
 	*x = MatchLabels{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[8]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[8]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -869,7 +869,7 @@ func (x *MatchLabels) String() string {
 func (*MatchLabels) ProtoMessage() {}
 
 func (x *MatchLabels) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[8]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[8]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -882,7 +882,7 @@ func (x *MatchLabels) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use MatchLabels.ProtoReflect.Descriptor instead.
 func (*MatchLabels) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{8}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *MatchLabels) GetLabels() map[string]string {
@@ -909,7 +909,7 @@ type ResponseMeta struct {
 
 func (x *ResponseMeta) Reset() {
 	*x = ResponseMeta{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -921,7 +921,7 @@ func (x *ResponseMeta) String() string {
 func (*ResponseMeta) ProtoMessage() {}
 
 func (x *ResponseMeta) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -934,7 +934,7 @@ func (x *ResponseMeta) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ResponseMeta.ProtoReflect.Descriptor instead.
 func (*ResponseMeta) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{9}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *ResponseMeta) GetTag() string {
@@ -965,7 +965,7 @@ type State struct {
 
 func (x *State) Reset() {
 	*x = State{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[10]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[10]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -977,7 +977,7 @@ func (x *State) String() string {
 func (*State) ProtoMessage() {}
 
 func (x *State) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[10]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[10]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -990,7 +990,7 @@ func (x *State) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use State.ProtoReflect.Descriptor instead.
 func (*State) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{10}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *State) GetComposite() *Resource {
@@ -1058,7 +1058,7 @@ type Resource struct {
 
 func (x *Resource) Reset() {
 	*x = Resource{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[11]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[11]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1070,7 +1070,7 @@ func (x *Resource) String() string {
 func (*Resource) ProtoMessage() {}
 
 func (x *Resource) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[11]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[11]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1083,7 +1083,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Resource.ProtoReflect.Descriptor instead.
 func (*Resource) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{11}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *Resource) GetResource() *structpb.Struct {
@@ -1126,7 +1126,7 @@ type Result struct {
 
 func (x *Result) Reset() {
 	*x = Result{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1138,7 +1138,7 @@ func (x *Result) String() string {
 func (*Result) ProtoMessage() {}
 
 func (x *Result) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1151,7 +1151,7 @@ func (x *Result) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Result.ProtoReflect.Descriptor instead.
 func (*Result) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{12}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *Result) GetSeverity() Severity {
@@ -1210,7 +1210,7 @@ type Condition struct {
 
 func (x *Condition) Reset() {
 	*x = Condition{}
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
@@ -1222,7 +1222,7 @@ func (x *Condition) String() string {
 func (*Condition) ProtoMessage() {}
 
 func (x *Condition) ProtoReflect() protoreflect.Message {
-	mi := &file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13]
+	mi := &file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1235,7 +1235,7 @@ func (x *Condition) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Condition.ProtoReflect.Descriptor instead.
 func (*Condition) Descriptor() ([]byte, []int) {
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{13}
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *Condition) GetType() string {
@@ -1273,284 +1273,284 @@ func (x *Condition) GetTarget() Target {
 	return Target_TARGET_UNSPECIFIED
 }
 
-var File_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto protoreflect.FileDescriptor
+var File_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto protoreflect.FileDescriptor
 
-var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc = []byte{
-	0x0a, 0x3e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
-	0x2f, 0x7a, 0x7a, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x75,
-	0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x12, 0x1e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
-	0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-	0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-	0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8e,
-	0x06, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62,
-	0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61,
-	0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76,
-	0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
+var file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc = []byte{
+	0x0a, 0x43, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31,
+	0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7a, 0x7a, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+	0x65, 0x64, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x62, 0x65, 0x74, 0x61, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x22, 0x8e, 0x06, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x6d, 0x65,
+	0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
 	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
-	0x08, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x07, 0x64, 0x65, 0x73,
-	0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69,
-	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
-	0x65, 0x52, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x05, 0x69, 0x6e,
-	0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75,
-	0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x88, 0x01, 0x01, 0x12, 0x36,
-	0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
-	0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x01, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74,
-	0x65, 0x78, 0x74, 0x88, 0x01, 0x01, 0x12, 0x6f, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f,
-	0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x46, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
+	0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x08, 0x6f,
+	0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
+	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53,
+	0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x3f,
+	0x0a, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x25, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
 	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
-	0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
-	0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x65, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65,
-	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x61,
-	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x75,
-	0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x1a, 0x6c,
-	0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+	0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x12,
+	0x32, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+	0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74,
+	0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x01, 0x52,
+	0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x88, 0x01, 0x01, 0x12, 0x6f, 0x0a, 0x0f, 0x65,
+	0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x06,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78,
+	0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x65, 0x0a, 0x0b,
+	0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x43, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74,
+	0x61, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
+	0x61, 0x6c, 0x73, 0x1a, 0x6c, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70,
+	0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x1a, 0x6b, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73,
 	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
 	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6b, 0x0a, 0x10,
-	0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x41, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74,
-	0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x69, 0x6e,
-	0x70, 0x75, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22,
-	0x72, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x59,
-	0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x64, 0x61, 0x74,
-	0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
-	0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65,
-	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
-	0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
-	0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
-	0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04,
-	0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a,
-	0x09, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x05, 0x69, 0x74,
-	0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65,
+	0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
+	0x61, 0x6c, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08,
+	0x0a, 0x06, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e,
+	0x74, 0x65, 0x78, 0x74, 0x22, 0x72, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
+	0x61, 0x6c, 0x73, 0x12, 0x59, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
+	0x6c, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72,
+	0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x0e,
+	0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x42, 0x08,
+	0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65,
+	0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x04, 0x64,
+	0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x65,
 	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xbb, 0x03, 0x0a, 0x13, 0x52,
-	0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
-	0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
-	0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04,
-	0x6d, 0x65, 0x74, 0x61, 0x12, 0x3f, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
+	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65,
+	0x6e, 0x74, 0x69, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e,
+	0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61, 0x74,
+	0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
+	0x38, 0x01, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12,
+	0x3e, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
+	0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66,
+	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e,
+	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22,
+	0xbb, 0x03, 0x0a, 0x13, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
 	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, 0x64, 0x65,
-	0x73, 0x69, 0x72, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73,
-	0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
-	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07,
-	0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65,
-	0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63,
-	0x74, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x88, 0x01, 0x01, 0x12,
-	0x50, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18,
-	0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65,
-	0x6e, 0x74, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
-	0x73, 0x12, 0x49, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
-	0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
-	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
-	0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0a, 0x0a, 0x08,
-	0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xee, 0x01, 0x0a, 0x0c, 0x52, 0x65,
-	0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x0f, 0x65, 0x78,
-	0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62,
-	0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
-	0x73, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x73, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e,
-	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52,
-	0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc3, 0x01, 0x0a, 0x10, 0x52,
-	0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12,
-	0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
-	0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-	0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x63,
-	0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c,
-	0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x70,
+	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d,
+	0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x3f, 0x0a, 0x07, 0x64, 0x65, 0x73,
+	0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
+	0x65, 0x52, 0x07, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x72, 0x65,
+	0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70,
 	0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x61, 0x74,
-	0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x63,
-	0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68,
-	0x22, 0x99, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
-	0x12, 0x4f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
+	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73,
+	0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x07,
+	0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+	0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+	0x74, 0x88, 0x01, 0x01, 0x12, 0x50, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d,
+	0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75,
+	0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+	0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74,
+	0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64,
+	0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x1f, 0x0a,
+	0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03,
+	0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xee,
+	0x01, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12,
+	0x69, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+	0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
+	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72,
+	0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72,
+	0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x73, 0x0a, 0x13, 0x45, 0x78,
+	0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65,
+	0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65,
+	0x63, 0x74, 0x6f, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
+	0xc3, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65,
+	0x63, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0a, 0x6d, 0x61, 0x74,
+	0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
+	0x09, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x6d, 0x61,
+	0x74, 0x63, 0x68, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x2b, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
 	0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
-	0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x2e, 0x4c, 0x61,
-	0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c,
-	0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5a, 0x0a, 0x0c,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03,
-	0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30,
-	0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
-	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x88, 0x01, 0x01,
-	0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x22, 0x8b, 0x02, 0x0a, 0x05, 0x53, 0x74, 0x61,
-	0x74, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
+	0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x00, 0x52,
+	0x0b, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x42, 0x07, 0x0a, 0x05,
+	0x6d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c,
+	0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x4f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18,
+	0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
 	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
-	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
-	0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x09, 0x72, 0x65,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e,
+	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x61, 0x62, 0x65,
+	0x6c, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06,
+	0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x22, 0x5a, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74,
+	0x61, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+	0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x03, 0x74,
+	0x74, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x74, 0x74, 0x6c, 0x22, 0x8b, 0x02,
+	0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+	0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x12,
+	0x52, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65,
+	0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+	0x63, 0x65, 0x73, 0x1a, 0x66, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65,
+	0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x02, 0x0a, 0x08,
+	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72,
+	0x75, 0x63, 0x74, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x6e, 0x0a,
+	0x12, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61,
+	0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x61, 0x70, 0x69, 0x65,
+	0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75,
+	0x72, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65,
+	0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x6e,
+	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x3b, 0x0a,
+	0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65,
+	0x61, 0x64, 0x79, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f,
+	0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+	0x22, 0xe0, 0x01, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x08, 0x73,
+	0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e,
 	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e,
 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53,
-	0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e,
-	0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x66,
-	0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
-	0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74,
-	0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08,
-	0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x6e,
-	0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
-	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
-	0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x43,
-	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
-	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
-	0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x3b, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64,
-	0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x05,
-	0x72, 0x65, 0x61, 0x64, 0x79, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
-	0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
-	0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
-	0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
-	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe0, 0x01, 0x0a, 0x06,
-	0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x44, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69,
-	0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
+	0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74,
+	0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x72,
+	0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72,
+	0x65, 0x61, 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67,
+	0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78,
 	0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69,
-	0x74, 0x79, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07,
-	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
-	0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62,
-	0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x01, 0x52, 0x06, 0x74,
-	0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61,
-	0x73, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xf2,
-	0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
-	0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
-	0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
-	0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
-	0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
-	0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x6d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65,
-	0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74,
-	0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48,
-	0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08,
-	0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72,
-	0x67, 0x65, 0x74, 0x2a, 0x3f, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x15, 0x0a, 0x11,
-	0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
-	0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x52, 0x55,
-	0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x46, 0x41, 0x4c,
-	0x53, 0x45, 0x10, 0x02, 0x2a, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79,
-	0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53,
-	0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x45,
-	0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14,
-	0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49,
-	0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59,
-	0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x56, 0x0a, 0x06, 0x54, 0x61, 0x72,
-	0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x55, 0x4e,
-	0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54,
-	0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x10,
-	0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50,
-	0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10,
-	0x02, 0x2a, 0x7f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x53,
-	0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
-	0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a,
-	0x18, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f,
-	0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x53,
+	0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
+	0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a,
+	0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x61, 0x72,
+	0x67, 0x65, 0x74, 0x22, 0xf2, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+	0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e,
+	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76,
+	0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a,
+	0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
+	0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x06,
+	0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61,
+	0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x54, 0x61,
+	0x72, 0x67, 0x65, 0x74, 0x48, 0x01, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x88, 0x01,
+	0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x09, 0x0a,
+	0x07, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2a, 0x3f, 0x0a, 0x05, 0x52, 0x65, 0x61, 0x64,
+	0x79, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44,
+	0x59, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x45, 0x41, 0x44,
+	0x59, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x02, 0x2a, 0x63, 0x0a, 0x08, 0x53, 0x65, 0x76,
+	0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54,
+	0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+	0x12, 0x0a, 0x0e, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x41, 0x54, 0x41,
+	0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x56, 0x45, 0x52, 0x49, 0x54, 0x59, 0x5f,
+	0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x56,
+	0x45, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x56,
+	0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47,
+	0x45, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+	0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f,
+	0x53, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54,
+	0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x43,
+	0x4c, 0x41, 0x49, 0x4d, 0x10, 0x02, 0x2a, 0x7f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
+	0x12, 0x20, 0x0a, 0x1c, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49,
+	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
+	0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e,
+	0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01,
+	0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49,
+	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53,
 	0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
-	0x54, 0x52, 0x55, 0x45, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
-	0x5f, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x4c, 0x53, 0x45,
-	0x10, 0x03, 0x32, 0x91, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
-	0x75, 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x78, 0x0a, 0x0b,
-	0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x2e, 0x61, 0x70,
-	0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x75, 0x6e,
-	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x33, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
-	0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
-	0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
-	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f,
-	0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
-	0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x66, 0x6e,
-	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x46, 0x41, 0x4c, 0x53, 0x45, 0x10, 0x03, 0x32, 0x91, 0x01, 0x0a, 0x15, 0x46, 0x75, 0x6e, 0x63,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+	0x65, 0x12, 0x78, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+	0x12, 0x32, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
+	0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
+	0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+	0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31,
+	0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
+	0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x46, 0x5a, 0x44, 0x67,
+	0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70,
+	0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f,
+	0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x65,
+	0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescOnce sync.Once
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData = file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescOnce sync.Once
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData = file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc
 )
 
-func file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP() []byte {
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescOnce.Do(func() {
-		file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData = protoimpl.X.CompressGZIP(file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData)
+func file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescGZIP() []byte {
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescOnce.Do(func() {
+		file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData = protoimpl.X.CompressGZIP(file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData)
 	})
-	return file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData
+	return file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDescData
 }
 
-var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
-var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
-var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes = []any{
+var file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
+var file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes = []any{
 	(Ready)(0),                  // 0: apiextensions.fn.proto.v1beta1.Ready
 	(Severity)(0),               // 1: apiextensions.fn.proto.v1beta1.Severity
 	(Target)(0),                 // 2: apiextensions.fn.proto.v1beta1.Target
@@ -1579,7 +1579,7 @@ var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes
 	(*structpb.Struct)(nil),     // 25: google.protobuf.Struct
 	(*durationpb.Duration)(nil), // 26: google.protobuf.Duration
 }
-var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs = []int32{
+var file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs = []int32{
 	9,  // 0: apiextensions.fn.proto.v1beta1.RunFunctionRequest.meta:type_name -> apiextensions.fn.proto.v1beta1.RequestMeta
 	14, // 1: apiextensions.fn.proto.v1beta1.RunFunctionRequest.observed:type_name -> apiextensions.fn.proto.v1beta1.State
 	14, // 2: apiextensions.fn.proto.v1beta1.RunFunctionRequest.desired:type_name -> apiextensions.fn.proto.v1beta1.State
@@ -1622,40 +1622,40 @@ var file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs
 	0,  // [0:33] is the sub-list for field type_name
 }
 
-func init() { file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_init() }
-func file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_init() {
-	if File_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto != nil {
+func init() { file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_init() }
+func file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_init() {
+	if File_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto != nil {
 		return
 	}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1].OneofWrappers = []any{
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[0].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[1].OneofWrappers = []any{
 		(*Credentials_CredentialData)(nil),
 	}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7].OneofWrappers = []any{
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[4].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[7].OneofWrappers = []any{
 		(*ResourceSelector_MatchName)(nil),
 		(*ResourceSelector_MatchLabels)(nil),
 	}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12].OneofWrappers = []any{}
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[9].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[12].OneofWrappers = []any{}
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes[13].OneofWrappers = []any{}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc,
+			RawDescriptor: file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc,
 			NumEnums:      4,
 			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
-		GoTypes:           file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes,
-		DependencyIndexes: file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs,
-		EnumInfos:         file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes,
-		MessageInfos:      file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes,
+		GoTypes:           file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes,
+		DependencyIndexes: file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs,
+		EnumInfos:         file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_enumTypes,
+		MessageInfos:      file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_msgTypes,
 	}.Build()
-	File_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto = out.File
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc = nil
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes = nil
-	file_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs = nil
+	File_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto = out.File
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_rawDesc = nil
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_goTypes = nil
+	file_apis_apiextensions_fn_proto_v1beta1_zz_generated_run_function_proto_depIdxs = nil
 }
diff --git a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
index 033bae718..d36b61db2 100644
--- a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
+++ b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
@@ -14,7 +14,7 @@
    limitations under the License.
 */
 
-// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/fn/proto/v1/run_function.proto by ./hack/duplicate_proto_type.sh. DO NOT EDIT.
 
 syntax = "proto3";
 
@@ -132,8 +132,8 @@ message RunFunctionResponse {
 
 // RequestMeta contains metadata pertaining to a RunFunctionRequest.
 message RequestMeta {
-  // An opaque string identifying the content of the request. Two identical
-  // requests should have the same tag.
+  // An opaque string identifying a request. Requests with identical tags will
+  // be otherwise identical.
   string tag = 1;
 }
 
diff --git a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function_grpc.pb.go b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function_grpc.pb.go
index ffdb67f76..130f6f3e7 100644
--- a/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function_grpc.pb.go
+++ b/apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function_grpc.pb.go
@@ -13,13 +13,13 @@
 //See the License for the specific language governing permissions and
 //limitations under the License.
 
-// Generated from apiextensions/fn/proto/v1/run_function.proto by ../hack/duplicate_proto_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/fn/proto/v1/run_function.proto by ./hack/duplicate_proto_type.sh. DO NOT EDIT.
 
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
 // - protoc-gen-go-grpc v1.3.0
 // - protoc             (unknown)
-// source: apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
+// source: apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto
 
 //buf:lint:ignore PACKAGE_DIRECTORY_MATCH // Too late to fix this now.
 
@@ -126,5 +126,5 @@ var FunctionRunnerService_ServiceDesc = grpc.ServiceDesc{
 		},
 	},
 	Streams:  []grpc.StreamDesc{},
-	Metadata: "apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto",
+	Metadata: "apis/apiextensions/fn/proto/v1beta1/zz_generated_run_function.proto",
 }
diff --git a/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go b/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go
index 87b884290..6ea863a9c 100644
--- a/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go
+++ b/apis/apiextensions/v1alpha1/zz_generated.environment_config_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1beta1/environment_config_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1beta1/environment_config_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1alpha1
 
diff --git a/apis/apiextensions/v1alpha1/zz_generated.usage_types.go b/apis/apiextensions/v1alpha1/zz_generated.usage_types.go
index 8226ca498..27d4cc12a 100644
--- a/apis/apiextensions/v1alpha1/zz_generated.usage_types.go
+++ b/apis/apiextensions/v1alpha1/zz_generated.usage_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1beta1/usage_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1beta1/usage_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1alpha1
 
diff --git a/apis/apiextensions/v1beta1/zz_generated.composition_common.go b/apis/apiextensions/v1beta1/zz_generated.composition_common.go
index ba1e7dfdb..7e1d53007 100644
--- a/apis/apiextensions/v1beta1/zz_generated.composition_common.go
+++ b/apis/apiextensions/v1beta1/zz_generated.composition_common.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1/composition_common.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1/composition_common.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/apiextensions/v1beta1/zz_generated.composition_patches.go b/apis/apiextensions/v1beta1/zz_generated.composition_patches.go
index 31de00894..67371b376 100644
--- a/apis/apiextensions/v1beta1/zz_generated.composition_patches.go
+++ b/apis/apiextensions/v1beta1/zz_generated.composition_patches.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1/composition_patches.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1/composition_patches.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/apiextensions/v1beta1/zz_generated.composition_revision_types.go b/apis/apiextensions/v1beta1/zz_generated.composition_revision_types.go
index 483d1b44c..96817b32a 100644
--- a/apis/apiextensions/v1beta1/zz_generated.composition_revision_types.go
+++ b/apis/apiextensions/v1beta1/zz_generated.composition_revision_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1/composition_revision_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1/composition_revision_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/apiextensions/v1beta1/zz_generated.composition_transforms.go b/apis/apiextensions/v1beta1/zz_generated.composition_transforms.go
index a8fcfeae8..94562f69d 100644
--- a/apis/apiextensions/v1beta1/zz_generated.composition_transforms.go
+++ b/apis/apiextensions/v1beta1/zz_generated.composition_transforms.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from apiextensions/v1/composition_transforms.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/apiextensions/v1/composition_transforms.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/meta/v1alpha1/zz_generated.configuration_types.go b/apis/pkg/meta/v1alpha1/zz_generated.configuration_types.go
index 1a5cfac7f..b5a084789 100644
--- a/apis/pkg/meta/v1alpha1/zz_generated.configuration_types.go
+++ b/apis/pkg/meta/v1alpha1/zz_generated.configuration_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/meta/v1/configuration_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/meta/v1/configuration_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1alpha1
 
diff --git a/apis/pkg/meta/v1alpha1/zz_generated.meta.go b/apis/pkg/meta/v1alpha1/zz_generated.meta.go
index c151497a5..91d780319 100644
--- a/apis/pkg/meta/v1alpha1/zz_generated.meta.go
+++ b/apis/pkg/meta/v1alpha1/zz_generated.meta.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/meta/v1/meta.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/meta/v1/meta.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1alpha1
 
diff --git a/apis/pkg/meta/v1alpha1/zz_generated.provider_types.go b/apis/pkg/meta/v1alpha1/zz_generated.provider_types.go
index 6e870fc92..42510675c 100644
--- a/apis/pkg/meta/v1alpha1/zz_generated.provider_types.go
+++ b/apis/pkg/meta/v1alpha1/zz_generated.provider_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/meta/v1/provider_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/meta/v1/provider_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1alpha1
 
diff --git a/apis/pkg/meta/v1beta1/zz_generated.function_types.go b/apis/pkg/meta/v1beta1/zz_generated.function_types.go
index 0698e1bcf..b361a068e 100644
--- a/apis/pkg/meta/v1beta1/zz_generated.function_types.go
+++ b/apis/pkg/meta/v1beta1/zz_generated.function_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/meta/v1/function_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/meta/v1/function_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/meta/v1beta1/zz_generated.meta.go b/apis/pkg/meta/v1beta1/zz_generated.meta.go
index 75d5f0bc4..607c40174 100644
--- a/apis/pkg/meta/v1beta1/zz_generated.meta.go
+++ b/apis/pkg/meta/v1beta1/zz_generated.meta.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/meta/v1/meta.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/meta/v1/meta.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/v1beta1/zz_generated.function_types.go b/apis/pkg/v1beta1/zz_generated.function_types.go
index c4d244d7f..62fb9f7b6 100644
--- a/apis/pkg/v1beta1/zz_generated.function_types.go
+++ b/apis/pkg/v1beta1/zz_generated.function_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/v1/function_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/v1/function_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/v1beta1/zz_generated.package_runtime_types.go b/apis/pkg/v1beta1/zz_generated.package_runtime_types.go
index 17134004c..6fc44451c 100644
--- a/apis/pkg/v1beta1/zz_generated.package_runtime_types.go
+++ b/apis/pkg/v1beta1/zz_generated.package_runtime_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/v1/package_runtime_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/v1/package_runtime_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/v1beta1/zz_generated.package_types.go b/apis/pkg/v1beta1/zz_generated.package_types.go
index aad03a3bd..4171be8b4 100644
--- a/apis/pkg/v1beta1/zz_generated.package_types.go
+++ b/apis/pkg/v1beta1/zz_generated.package_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/v1/package_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/v1/package_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/pkg/v1beta1/zz_generated.revision_types.go b/apis/pkg/v1beta1/zz_generated.revision_types.go
index 6fb2135e0..b9873d599 100644
--- a/apis/pkg/v1beta1/zz_generated.revision_types.go
+++ b/apis/pkg/v1beta1/zz_generated.revision_types.go
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Generated from pkg/v1/revision_types.go by ../hack/duplicate_api_type.sh. DO NOT EDIT.
+// Generated from apis/pkg/v1/revision_types.go by ./hack/duplicate_api_type.sh. DO NOT EDIT.
 
 package v1beta1
 
diff --git a/apis/buf.gen.yaml b/buf.gen.yaml
similarity index 100%
rename from apis/buf.gen.yaml
rename to buf.gen.yaml
diff --git a/apis/buf.lock b/buf.lock
similarity index 100%
rename from apis/buf.lock
rename to buf.lock
diff --git a/apis/buf.yaml b/buf.yaml
similarity index 100%
rename from apis/buf.yaml
rename to buf.yaml
diff --git a/cluster/charts/crossplane/README.md b/cluster/charts/crossplane/README.md
index df0fbdc0a..09701415a 100644
--- a/cluster/charts/crossplane/README.md
+++ b/cluster/charts/crossplane/README.md
@@ -78,6 +78,9 @@ and their default values.
 | `extraVolumeMountsCrossplane` | Add custom `volumeMounts` to the Crossplane pod. | `{}` |
 | `extraVolumesCrossplane` | Add custom `volumes` to the Crossplane pod. | `{}` |
 | `function.packages` | A list of Function packages to install | `[]` |
+| `functionCache.medium` | Set to `Memory` to hold the function cache in a RAM backed file system. Useful for Crossplane development. | `""` |
+| `functionCache.pvc` | The name of a PersistentVolumeClaim to use as the function cache. Disables the default function cache `emptyDir` Volume. | `""` |
+| `functionCache.sizeLimit` | The size limit for the function cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. | `"512Mi"` |
 | `hostNetwork` | Enable `hostNetwork` for the Crossplane deployment. Caution: enabling `hostNetwork` grants the Crossplane Pod access to the host network namespace. Consider setting `dnsPolicy` to `ClusterFirstWithHostNet`. | `false` |
 | `image.pullPolicy` | The image pull policy used for Crossplane and RBAC Manager pods. | `"IfNotPresent"` |
 | `image.repository` | Repository for the Crossplane pod image. | `"xpkg.crossplane.io/crossplane/crossplane"` |
@@ -91,7 +94,6 @@ and their default values.
 | `packageCache.medium` | Set to `Memory` to hold the package cache in a RAM backed file system. Useful for Crossplane development. | `""` |
 | `packageCache.pvc` | The name of a PersistentVolumeClaim to use as the package cache. Disables the default package cache `emptyDir` Volume. | `""` |
 | `packageCache.sizeLimit` | The size limit for the package cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. | `"20Mi"` |
-| `packageManager.enableAutomaticDependencyDowngrade` | Enable automatic dependency version downgrades. This configuration is only used when `--enable-dependency-version-upgrades` flag is passed. | `false` |
 | `podSecurityContextCrossplane` | Add a custom `securityContext` to the Crossplane pod. | `{}` |
 | `podSecurityContextRBACManager` | Add a custom `securityContext` to the RBAC Manager pod. | `{}` |
 | `priorityClassName` | The PriorityClass name to apply to the Crossplane and RBAC Manager pods. | `""` |
diff --git a/cluster/charts/crossplane/templates/deployment.yaml b/cluster/charts/crossplane/templates/deployment.yaml
index 48bb1c8a4..844eca76d 100644
--- a/cluster/charts/crossplane/templates/deployment.yaml
+++ b/cluster/charts/crossplane/templates/deployment.yaml
@@ -212,13 +212,11 @@ spec:
           - name: {{ $key | replace "." "_" }}
             value: {{ $value | quote }}
         {{- end}}
-        {{- if .Values.packageManager.enableAutomaticDependencyDowngrade }}
-          - name: "AUTOMATIC_DEPENDENCY_DOWNGRADE_ENABLED"
-            value: "true"
-        {{- end }}
         volumeMounts:
-          - mountPath: /cache
+          - mountPath: /cache/xpkg
             name: package-cache
+          - mountPath: /cache/xfn
+            name: function-cache
           {{- if .Values.registryCaBundleConfig.name }}
           - mountPath: /certs
             name: ca-certs
@@ -243,6 +241,15 @@ spec:
           medium: {{ .Values.packageCache.medium }}
           sizeLimit: {{ .Values.packageCache.sizeLimit }}
         {{- end }}
+      - name: function-cache
+        {{- if .Values.functionCache.pvc }}
+        persistentVolumeClaim:
+          claimName: {{ .Values.functionCache.pvc }}
+        {{- else }}
+        emptyDir:
+          medium: {{ .Values.functionCache.medium }}
+          sizeLimit: {{ .Values.functionCache.sizeLimit }}
+        {{- end }}
       {{- if .Values.registryCaBundleConfig.name }}
       - name: ca-certs
         configMap:
diff --git a/cluster/charts/crossplane/values.yaml b/cluster/charts/crossplane/values.yaml
index 34857580a..719dfd1fa 100755
--- a/cluster/charts/crossplane/values.yaml
+++ b/cluster/charts/crossplane/values.yaml
@@ -105,10 +105,6 @@ rbacManager:
   # -- Add `topologySpreadConstraints` to the RBAC Manager pod deployment.
   topologySpreadConstraints: []
 
-packageManager:
-  # -- Enable automatic dependency version downgrades. This configuration is only used when `--enable-dependency-version-upgrades` flag is passed.
-  enableAutomaticDependencyDowngrade: false
-
 # -- The PriorityClass name to apply to the Crossplane and RBAC Manager pods.
 priorityClassName: ""
 
@@ -147,6 +143,14 @@ packageCache:
   # -- The name of a ConfigMap to use as the package cache. Disables the default package cache `emptyDir` Volume.
   configMap: ""
 
+functionCache:
+  # -- Set to `Memory` to hold the function cache in a RAM backed file system. Useful for Crossplane development.
+  medium: ""
+  # -- The size limit for the function cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory.
+  sizeLimit: 512Mi
+  # -- The name of a PersistentVolumeClaim to use as the function cache. Disables the default function cache `emptyDir` Volume.
+  pvc: ""
+
 resourcesRBACManager:
   limits:
     # -- CPU resource limits for the RBAC Manager pod.
diff --git a/cmd/crank/beta/convert/compositionenvironment/cmd.go b/cmd/crank/beta/convert/compositionenvironment/cmd.go
index 4c291c245..c6d04120a 100644
--- a/cmd/crank/beta/convert/compositionenvironment/cmd.go
+++ b/cmd/crank/beta/convert/compositionenvironment/cmd.go
@@ -36,10 +36,10 @@ import (
 // Cmd arguments and flags for converting a Composition to use function-environment-configs.
 type Cmd struct {
 	// Arguments.
-	InputFile string `arg:"" default:"-" help:"The Composition file to be converted. If not specified or '-', stdin will be used." optional:"" type:"path"`
+	InputFile string `arg:"" default:"-" help:"The Composition file to be converted. If not specified or '-', stdin will be used." optional:"" predictor:"file" type:"path"`
 
 	// Flags.
-	OutputFile string `help:"The file to write the generated Composition to. If not specified, stdout will be used." placeholder:"PATH" short:"o" type:"path"`
+	OutputFile string `help:"The file to write the generated Composition to. If not specified, stdout will be used." placeholder:"PATH" predictor:"file" short:"o" type:"path"`
 
 	FunctionEnvironmentConfigRef string `default:"function-environment-configs" help:"Name of the existing function-environment-configs Function, to be used to reference it." name:"function-environment-configs-ref"`
 
diff --git a/cmd/crank/beta/convert/deploymentruntime/cmd.go b/cmd/crank/beta/convert/deploymentruntime/cmd.go
index f1ada34f7..d3b3dd1bc 100644
--- a/cmd/crank/beta/convert/deploymentruntime/cmd.go
+++ b/cmd/crank/beta/convert/deploymentruntime/cmd.go
@@ -34,10 +34,10 @@ import (
 // Cmd arguments and flags for convert deployment-runtime subcommand.
 type Cmd struct {
 	// Arguments.
-	InputFile string `arg:"" default:"-" help:"The ControllerConfig file to be Converted. If not specified or '-', stdin will be used." optional:"" type:"path"`
+	InputFile string `arg:"" default:"-" help:"The ControllerConfig file to be Converted. If not specified or '-', stdin will be used." optional:"" predictor:"file" type:"path"`
 
 	// Flags.
-	OutputFile string `help:"The file to write the generated DeploymentRuntimeConfig to. If not specified, stdout will be used." placeholder:"PATH" short:"o" type:"path"`
+	OutputFile string `help:"The file to write the generated DeploymentRuntimeConfig to. If not specified, stdout will be used." placeholder:"PATH" predictor:"file" short:"o" type:"path"`
 
 	fs afero.Fs
 }
diff --git a/cmd/crank/beta/convert/pipelinecomposition/cmd.go b/cmd/crank/beta/convert/pipelinecomposition/cmd.go
index d7775db83..bc9f77e87 100644
--- a/cmd/crank/beta/convert/pipelinecomposition/cmd.go
+++ b/cmd/crank/beta/convert/pipelinecomposition/cmd.go
@@ -36,10 +36,10 @@ import (
 // Cmd arguments and flags for converting a patch-and-transform to a function pipeline composition.
 type Cmd struct {
 	// Arguments.
-	InputFile string `arg:"" default:"-" help:"The Composition file to be converted. If not specified or '-', stdin will be used." optional:"" type:"path"`
+	InputFile string `arg:"" default:"-" help:"The Composition file to be converted. If not specified or '-', stdin will be used." optional:"" predictor:"file" type:"path"`
 
 	// Flags.
-	OutputFile string `help:"The file to write the generated Composition to. If not specified, stdout will be used." placeholder:"PATH" short:"o" type:"path"`
+	OutputFile string `help:"The file to write the generated Composition to. If not specified, stdout will be used." placeholder:"PATH" predictor:"file" short:"o" type:"path"`
 
 	FunctionPatchAndTransformRef string `default:"function-patch-and-transform" help:"Name of the existing function-patch-and-transform Function, to be used to reference it." name:"function-patch-and-transform-ref"`
 	FunctionEnvironmentConfigRef string `default:"function-environment-configs" help:"Name of the existing function-environment-configs Function, to be used to reference it." name:"function-environment-configs-ref"`
diff --git a/cmd/crank/beta/top/top.go b/cmd/crank/beta/top/top.go
index 47c375df5..33e32e975 100644
--- a/cmd/crank/beta/top/top.go
+++ b/cmd/crank/beta/top/top.go
@@ -52,7 +52,7 @@ const (
 // Cmd represents the top command.
 type Cmd struct {
 	Summary   bool   `help:"Adds summary header for all Crossplane pods." name:"summary"                                                             short:"s"`
-	Namespace string `default:"crossplane-system"                         help:"Show pods from a specific namespace, defaults to crossplane-system." name:"namespace" short:"n"`
+	Namespace string `default:"crossplane-system"                         help:"Show pods from a specific namespace, defaults to crossplane-system." name:"namespace" predictor:"namespace" short:"n"`
 }
 
 // Help returns help instructions for the top command.
diff --git a/cmd/crank/beta/trace/internal/resource/client.go b/cmd/crank/beta/trace/internal/resource/client.go
index 3e292023e..6b0090313 100644
--- a/cmd/crank/beta/trace/internal/resource/client.go
+++ b/cmd/crank/beta/trace/internal/resource/client.go
@@ -18,67 +18,19 @@ package resource
 
 import (
 	"context"
-	"fmt"
 
 	v1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/meta"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/runtime/schema"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	xpmeta "github.com/crossplane/crossplane-runtime/pkg/meta"
 )
 
-const (
-	errFmtResourceTypeNotFound = "the server doesn't have a resource type %q"
-)
-
 // TreeClient is the interface to get a Resource with all its children.
 type TreeClient interface {
 	GetResourceTree(ctx context.Context, root *Resource) (*Resource, error)
 }
 
-// MappingFor returns the RESTMapping for the given resource or kind argument.
-// Copied over from cli-runtime pkg/resource Builder,
-// https://github.com/kubernetes/cli-runtime/blob/9a91d944dd43186c52e0162e12b151b0e460354a/pkg/resource/builder.go#L768
-func MappingFor(rmapper meta.RESTMapper, resourceOrKindArg string) (*meta.RESTMapping, error) {
-	// TODO(phisco): actually use the Builder.
-	fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg)
-	gvk := schema.GroupVersionKind{}
-	if fullySpecifiedGVR != nil {
-		gvk, _ = rmapper.KindFor(*fullySpecifiedGVR)
-	}
-	if gvk.Empty() {
-		gvk, _ = rmapper.KindFor(groupResource.WithVersion(""))
-	}
-	if !gvk.Empty() {
-		return rmapper.RESTMapping(gvk.GroupKind(), gvk.Version)
-	}
-	fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg)
-	if fullySpecifiedGVK == nil {
-		gvk := groupKind.WithVersion("")
-		fullySpecifiedGVK = &gvk
-	}
-	if !fullySpecifiedGVK.Empty() {
-		if mapping, err := rmapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil {
-			return mapping, nil
-		}
-	}
-	mapping, err := rmapper.RESTMapping(groupKind, gvk.Version)
-	if err != nil {
-		// if we error out here, it is because we could not match a resource or a kind
-		// for the given argument. To maintain consistency with previous behavior,
-		// announce that a resource type could not be found.
-		// if the error is _not_ a *meta.NoKindMatchError, then we had trouble doing discovery,
-		// so we should return the original error since it may help a user diagnose what is actually wrong
-		if meta.IsNoMatchError(err) {
-			return nil, fmt.Errorf(errFmtResourceTypeNotFound, groupResource.Resource)
-		}
-		return nil, err
-	}
-	return mapping, nil
-}
-
 // GetResource returns the requested Resource, setting any error as Resource.Error.
 func GetResource(ctx context.Context, client client.Client, ref *v1.ObjectReference) *Resource {
 	result := unstructured.Unstructured{}
diff --git a/cmd/crank/beta/trace/trace.go b/cmd/crank/beta/trace/trace.go
index 924c05934..af57fb14d 100644
--- a/cmd/crank/beta/trace/trace.go
+++ b/cmd/crank/beta/trace/trace.go
@@ -39,6 +39,7 @@ import (
 	"github.com/crossplane/crossplane/cmd/crank/beta/trace/internal/resource"
 	"github.com/crossplane/crossplane/cmd/crank/beta/trace/internal/resource/xpkg"
 	"github.com/crossplane/crossplane/cmd/crank/beta/trace/internal/resource/xrm"
+	"github.com/crossplane/crossplane/cmd/crank/internal"
 )
 
 const (
@@ -58,12 +59,12 @@ const (
 
 // Cmd builds the trace tree for a Crossplane resource.
 type Cmd struct {
-	Resource string `arg:"" help:"Kind of the Crossplane resource, accepts the 'TYPE[.VERSION][.GROUP][/NAME]' format."`
-	Name     string `arg:"" help:"Name of the Crossplane resource, can be passed as part of the resource too."          optional:""`
+	Resource string `arg:"" help:"Kind of the Crossplane resource, accepts the 'TYPE[.VERSION][.GROUP][/NAME]' format." predictor:"k8s_resource"`
+	Name     string `arg:"" help:"Name of the Crossplane resource, can be passed as part of the resource too."          optional:""              predictor:"k8s_resource_name"`
 
 	// TODO(phisco): add support for all the usual kubectl flags; configFlags := genericclioptions.NewConfigFlags(true).AddFlags(...)
-	Context                   string `default:""                                    help:"Kubernetes context."                         name:"context"                                                             short:"c"`
-	Namespace                 string `default:""                                    help:"Namespace of the resource."                  name:"namespace"                                                           short:"n"`
+	Context                   string `default:""                                    help:"Kubernetes context."                         name:"context"                                                             predictor:"context"              short:"c"`
+	Namespace                 string `default:""                                    help:"Namespace of the resource."                  name:"namespace"                                                           predictor:"namespace"            short:"n"`
 	Output                    string `default:"default"                             enum:"default,wide,json,dot"                       help:"Output format. One of: default, wide, json, dot."                    name:"output"                    short:"o"`
 	ShowConnectionSecrets     bool   `help:"Show connection secrets in the output." name:"show-connection-secrets"                     short:"s"`
 	ShowPackageDependencies   string `default:"unique"                              enum:"unique,all,none"                             help:"Show package dependencies in the output. One of: unique, all, none." name:"show-package-dependencies"`
@@ -165,7 +166,7 @@ func (c *Cmd) Run(k *kong.Context, logger logging.Logger) error {
 		return errors.Wrap(err, errInvalidResourceAndName)
 	}
 
-	mapping, err := resource.MappingFor(rmapper, res)
+	mapping, err := internal.MappingFor(rmapper, res)
 	if err != nil {
 		return errors.Wrap(err, errGetMapping)
 	}
diff --git a/cmd/crank/beta/validate/cmd.go b/cmd/crank/beta/validate/cmd.go
index b2c239bfe..62f866d86 100644
--- a/cmd/crank/beta/validate/cmd.go
+++ b/cmd/crank/beta/validate/cmd.go
@@ -40,7 +40,7 @@ type Cmd struct {
 	Resources  string `arg:"" help:"Resources source which can be a file, directory, or '-' for standard input."`
 
 	// Flags. Keep them in alphabetical order.
-	CacheDir              string `default:"~/.crossplane/cache"                                                       help:"Absolute path to the cache directory where downloaded schemas are stored."`
+	CacheDir              string `default:"~/.crossplane/cache"                                                       help:"Absolute path to the cache directory where downloaded schemas are stored." predictor:"directory"`
 	CleanCache            bool   `help:"Clean the cache directory before downloading package schemas."`
 	SkipSuccessResults    bool   `help:"Skip printing success results."`
 	CrossplaneImage       string `help:"Specify the Crossplane image to be used for validating the built-in schemas."`
diff --git a/cmd/crank/completion/completion.go b/cmd/crank/completion/completion.go
new file mode 100644
index 000000000..dc79c20b4
--- /dev/null
+++ b/cmd/crank/completion/completion.go
@@ -0,0 +1,262 @@
+// Package completion contains Crossplane CLI completions.
+package completion
+
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	"github.com/posener/complete"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/client-go/discovery"
+	"k8s.io/client-go/discovery/cached/memory"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+	"k8s.io/client-go/restmapper"
+	"k8s.io/client-go/tools/clientcmd"
+	controllerClient "sigs.k8s.io/controller-runtime/pkg/client"
+
+	"github.com/crossplane/crossplane/cmd/crank/internal"
+)
+
+// Predictors returns all supported predictors.
+func Predictors() map[string]complete.Predictor {
+	yamlPredictor := complete.PredictOr(
+		complete.PredictFiles("*.yml"),
+		complete.PredictFiles("*.yaml"),
+	)
+	return map[string]complete.Predictor{
+		"file":                   complete.PredictFiles("*"),
+		"xpkg_file":              complete.PredictFiles("*.xpkg"),
+		"yaml_file":              yamlPredictor,
+		"directory":              complete.PredictDirs("*"),
+		"file_or_directory":      complete.PredictOr(complete.PredictFiles("*"), complete.PredictDirs("*")),
+		"yaml_file_or_directory": complete.PredictOr(yamlPredictor, complete.PredictDirs("*")),
+		"namespace":              namespacePredictor(),
+		"context":                contextPredictor(),
+		"k8s_resource":           kubernetesResourcePredictor(),
+		"k8s_resource_name":      kubernetesResourceNamePredictor(),
+	}
+}
+
+// kubernetesResourcePredictor returns a predictor that suggests Kubernetes resources based on
+// the current context and namespace or the context and namespace specified in the command line arguments.
+// It uses the Kubernetes client to retrieve the available resources and filters them based on the
+// last completed argument.
+func kubernetesResourcePredictor() complete.PredictFunc {
+	return func(a complete.Args) []string {
+		_, kubeconfig, _, err := kubernetesClient(parseConfigOverride(a))
+		if err != nil {
+			return nil
+		}
+
+		discoveryClient, err := discovery.NewDiscoveryClientForConfig(kubeconfig)
+		if err != nil {
+			return nil
+		}
+
+		resources, err := discoveryClient.ServerPreferredResources()
+		if err != nil {
+			return nil
+		}
+
+		if len(resources) == 0 {
+			return nil
+		}
+
+		var predictions []string
+		for _, apiResources := range resources {
+			for _, res := range apiResources.APIResources {
+				var resourceName string
+
+				// Write the resource name in a normalized format <name>.<version>.<group>
+				// or <name>.<version> if the group is empty.
+				// If the version is empty, just use the name.
+				switch {
+				case res.Group != "" && res.Version != "":
+					resourceName = fmt.Sprintf("%s.%s.%s", res.Name, res.Version, res.Group)
+				case res.Version != "":
+					resourceName = fmt.Sprintf("%s.%s", res.Name, res.Version)
+				default:
+					resourceName = res.Name
+				}
+
+				// This way we can filter the resources by the last completed argument of any valid format
+				// by just cheking the prefix.
+				if strings.HasPrefix(resourceName, a.Last) {
+					predictions = append(predictions, resourceName)
+				}
+			}
+		}
+		return predictions
+	}
+}
+
+// kubernetesResourceNamePredictor returns a predictor that suggests Kubernetes resource names based on
+// the current context and namespace or the context and namespace specified in the command line arguments.
+// It uses the Kubernetes client to retrieve the available resources and filters them based on the
+// last completed argument.
+func kubernetesResourceNamePredictor() complete.PredictFunc {
+	return func(a complete.Args) []string {
+		client, kubeconfig, clientconfig, err := kubernetesClient(parseConfigOverride(a))
+		if err != nil {
+			return nil
+		}
+
+		discoveryClient, err := discovery.NewDiscoveryClientForConfig(kubeconfig)
+		if err != nil {
+			return nil
+		}
+
+		d := memory.NewMemCacheClient(discoveryClient)
+		// If the previously completed argument (resource name) was used by its short form, we need to
+		// get the full resource name to be able to list the resources.
+		rmapper := restmapper.NewShortcutExpander(restmapper.NewDeferredDiscoveryRESTMapper(d), d, nil)
+		mapping, err := internal.MappingFor(rmapper, a.LastCompleted)
+		if err != nil {
+			return nil
+		}
+
+		u := &unstructured.UnstructuredList{}
+		u.SetGroupVersionKind(schema.GroupVersionKind{
+			Kind:    mapping.GroupVersionKind.Kind,
+			Group:   mapping.GroupVersionKind.Group,
+			Version: mapping.GroupVersionKind.Version,
+		})
+
+		// Limit the search results to the current context and namespace or the context and namespace specified in the command line arguments.
+		// If no namespace is specified, it will try to use the current context namespace.
+		// If that fails, it will use the default namespace.
+		namespace := parseNamespaceOverride(a)
+		if namespace == "" {
+			namespace, _, err = clientconfig.Namespace()
+			if err != nil || namespace == "" {
+				namespace = metav1.NamespaceDefault
+			}
+		}
+		err = client.List(context.Background(), u, controllerClient.InNamespace(namespace))
+		if err != nil {
+			return nil
+		}
+
+		// Find predictions by filtering the resource names that start with the currently completed argument.
+		var predictions []string
+		for _, res := range u.Items {
+			if strings.HasPrefix(res.GetName(), a.Last) {
+				predictions = append(predictions, res.GetName())
+			}
+		}
+		return predictions
+	}
+}
+
+// contextPredictor returns a predictor that suggests Kubernetes contexts from the KUBECONFIG.
+func contextPredictor() complete.PredictFunc {
+	return func(a complete.Args) []string {
+		clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
+			clientcmd.NewDefaultClientConfigLoadingRules(),
+			&clientcmd.ConfigOverrides{},
+		)
+
+		kubeConfig, err := clientConfig.RawConfig()
+		if err != nil {
+			return nil
+		}
+
+		var predictions []string
+		for name := range kubeConfig.Contexts {
+			if strings.HasPrefix(name, a.Last) {
+				predictions = append(predictions, name)
+			}
+		}
+		return predictions
+	}
+}
+
+// namespacePredictor returns a predictor that suggests Kubernetes namespaces from the current context.
+// It uses the Kubernetes client to retrieve the available namespaces and filters them based on the
+// last completed argument.
+func namespacePredictor() complete.PredictFunc {
+	return func(a complete.Args) []string {
+		client, err := kubernetesClientset()
+		if err != nil {
+			return nil
+		}
+
+		namespaceList, err := client.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
+		if err != nil {
+			return nil
+		}
+
+		var predictions []string
+		for _, ns := range namespaceList.Items {
+			if strings.HasPrefix(ns.GetName(), a.Last) {
+				predictions = append(predictions, ns.GetName())
+			}
+		}
+		return predictions
+	}
+}
+
+// kubernetesClientset returns a Kubernetes clientset using the default kubeconfig.
+func kubernetesClientset() (*kubernetes.Clientset, error) {
+	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
+		clientcmd.NewDefaultClientConfigLoadingRules(),
+		&clientcmd.ConfigOverrides{},
+	)
+
+	kubeConfig, err := clientConfig.ClientConfig()
+	if err != nil {
+		return nil, err
+	}
+
+	return kubernetes.NewForConfig(kubeConfig)
+}
+
+// kubernetesClient returns a Kubernetes client and a rest.Config using the provided config overrides.
+func kubernetesClient(configOverrides *clientcmd.ConfigOverrides) (controllerClient.Client, *rest.Config, clientcmd.ClientConfig, error) {
+	clientconfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
+		clientcmd.NewDefaultClientConfigLoadingRules(),
+		configOverrides,
+	)
+
+	kubeconfig, err := clientconfig.ClientConfig()
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	client, err := controllerClient.New(rest.CopyConfig(kubeconfig), controllerClient.Options{})
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	return client, rest.CopyConfig(kubeconfig), clientconfig, nil
+}
+
+// parseConfigOverride parses ConfigOverrides for the k8s client from the completed command line arguments.
+func parseConfigOverride(a complete.Args) *clientcmd.ConfigOverrides {
+	context := ""
+	for i, arg := range a.All {
+		if (arg == "--context" || arg == "-c") && i < len(a.All) {
+			context = a.All[i+1]
+			break
+		}
+	}
+	return &clientcmd.ConfigOverrides{
+		CurrentContext: context,
+	}
+}
+
+// parseNamespaceOverride parses the namespace override from the completed command line arguments.
+func parseNamespaceOverride(a complete.Args) string {
+	namespace := ""
+	for i, arg := range a.All {
+		if (arg == "--namespace" || arg == "-n") && i < len(a.All) {
+			namespace = a.All[i+1]
+			break
+		}
+	}
+	return namespace
+}
diff --git a/cmd/crank/internal/client.go b/cmd/crank/internal/client.go
new file mode 100644
index 000000000..18a5154cb
--- /dev/null
+++ b/cmd/crank/internal/client.go
@@ -0,0 +1,54 @@
+// Package internal contains internally used logic for Crossplane CLI.
+package internal
+
+import (
+	"fmt"
+
+	"k8s.io/apimachinery/pkg/api/meta"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+const (
+	errFmtResourceTypeNotFound = "the server doesn't have a resource type %q"
+)
+
+// MappingFor returns the RESTMapping for the given resource or kind argument.
+// Copied over from cli-runtime pkg/resource Builder,
+// https://github.com/kubernetes/cli-runtime/blob/9a91d944dd43186c52e0162e12b151b0e460354a/pkg/resource/builder.go#L768
+func MappingFor(rmapper meta.RESTMapper, resourceOrKindArg string) (*meta.RESTMapping, error) {
+	// TODO(phisco): actually use the Builder.
+	fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg)
+	gvk := schema.GroupVersionKind{}
+	if fullySpecifiedGVR != nil {
+		gvk, _ = rmapper.KindFor(*fullySpecifiedGVR)
+	}
+	if gvk.Empty() {
+		gvk, _ = rmapper.KindFor(groupResource.WithVersion(""))
+	}
+	if !gvk.Empty() {
+		return rmapper.RESTMapping(gvk.GroupKind(), gvk.Version)
+	}
+	fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg)
+	if fullySpecifiedGVK == nil {
+		gvk := groupKind.WithVersion("")
+		fullySpecifiedGVK = &gvk
+	}
+	if !fullySpecifiedGVK.Empty() {
+		if mapping, err := rmapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil {
+			return mapping, nil
+		}
+	}
+	mapping, err := rmapper.RESTMapping(groupKind, gvk.Version)
+	if err != nil {
+		// if we error out here, it is because we could not match a resource or a kind
+		// for the given argument. To maintain consistency with previous behavior,
+		// announce that a resource type could not be found.
+		// if the error is _not_ a *meta.NoKindMatchError, then we had trouble doing discovery,
+		// so we should return the original error since it may help a user diagnose what is actually wrong
+		if meta.IsNoMatchError(err) {
+			return nil, fmt.Errorf(errFmtResourceTypeNotFound, groupResource.Resource)
+		}
+		return nil, err
+	}
+	return mapping, nil
+}
diff --git a/cmd/crank/main.go b/cmd/crank/main.go
index ff4594f24..91342631c 100644
--- a/cmd/crank/main.go
+++ b/cmd/crank/main.go
@@ -18,12 +18,16 @@ limitations under the License.
 package main
 
 import (
+	"os"
+
 	"github.com/alecthomas/kong"
+	"github.com/willabides/kongplete"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 
 	"github.com/crossplane/crossplane-runtime/pkg/logging"
 
 	"github.com/crossplane/crossplane/cmd/crank/beta"
+	"github.com/crossplane/crossplane/cmd/crank/completion"
 	"github.com/crossplane/crossplane/cmd/crank/render"
 	"github.com/crossplane/crossplane/cmd/crank/version"
 	"github.com/crossplane/crossplane/cmd/crank/xpkg"
@@ -57,11 +61,14 @@ type cli struct {
 
 	// Flags.
 	Verbose verboseFlag `help:"Print verbose logging statements." name:"verbose"`
+
+	// Completion
+	Completions kongplete.InstallCompletions `cmd:"" help:"Get shell (bash/zsh/fish) completions. You can source this command to get completions for the login shell. Example: 'source <(crossplane completions)'"`
 }
 
 func main() {
 	logger := logging.NewNopLogger()
-	ctx := kong.Parse(&cli{},
+	parser := kong.Must(&cli{},
 		kong.Name("crossplane"),
 		kong.Description("A command line tool for interacting with Crossplane."),
 		// Binding a variable to kong context makes it available to all commands
@@ -73,6 +80,14 @@ func main() {
 			WrapUpperBound: 80,
 		}),
 		kong.UsageOnError())
-	err := ctx.Run()
+
+	kongplete.Complete(parser,
+		kongplete.WithPredictors(completion.Predictors()),
+	)
+
+	ctx, err := parser.Parse(os.Args[1:])
+	parser.FatalIfErrorf(err)
+
+	err = ctx.Run()
 	ctx.FatalIfErrorf(err)
 }
diff --git a/cmd/crank/render/cmd.go b/cmd/crank/render/cmd.go
index f1617ad91..addf85683 100644
--- a/cmd/crank/render/cmd.go
+++ b/cmd/crank/render/cmd.go
@@ -39,19 +39,19 @@ import (
 // Cmd arguments and flags for render subcommand.
 type Cmd struct {
 	// Arguments.
-	CompositeResource string `arg:"" help:"A YAML file specifying the composite resource (XR) to render."                                        type:"existingfile"`
-	Composition       string `arg:"" help:"A YAML file specifying the Composition to use to render the XR. Must be mode: Pipeline."              type:"existingfile"`
-	Functions         string `arg:"" help:"A YAML file or directory of YAML files specifying the Composition Functions to use to render the XR." type:"path"`
+	CompositeResource string `arg:"" help:"A YAML file specifying the composite resource (XR) to render."                                        predictor:"yaml_file"              type:"existingfile"`
+	Composition       string `arg:"" help:"A YAML file specifying the Composition to use to render the XR. Must be mode: Pipeline."              predictor:"yaml_file"              type:"existingfile"`
+	Functions         string `arg:"" help:"A YAML file or directory of YAML files specifying the Composition Functions to use to render the XR." predictor:"yaml_file_or_directory" type:"path"`
 
 	// Flags. Keep them in alphabetical order.
-	ContextFiles           map[string]string `help:"Comma-separated context key-value pairs to pass to the Function pipeline. Values must be files containing JSON."                           mapsep:""`
+	ContextFiles           map[string]string `help:"Comma-separated context key-value pairs to pass to the Function pipeline. Values must be files containing JSON."                           mapsep:""          predictor:"file"`
 	ContextValues          map[string]string `help:"Comma-separated context key-value pairs to pass to the Function pipeline. Values must be JSON. Keys take precedence over --context-files." mapsep:""`
 	IncludeFunctionResults bool              `help:"Include informational and warning messages from Functions in the rendered output as resources of kind: Result."                            short:"r"`
 	IncludeFullXR          bool              `help:"Include a direct copy of the input XR's spec and metadata fields in the rendered output."                                                  short:"x"`
-	ObservedResources      string            `help:"A YAML file or directory of YAML files specifying the observed state of composed resources."                                               placeholder:"PATH" short:"o"   type:"path"`
-	ExtraResources         string            `help:"A YAML file or directory of YAML files specifying extra resources to pass to the Function pipeline."                                       placeholder:"PATH" short:"e"   type:"path"`
+	ObservedResources      string            `help:"A YAML file or directory of YAML files specifying the observed state of composed resources."                                               placeholder:"PATH" predictor:"yaml_file_or_directory" short:"o"   type:"path"`
+	ExtraResources         string            `help:"A YAML file or directory of YAML files specifying extra resources to pass to the Function pipeline."                                       placeholder:"PATH" predictor:"yaml_file_or_directory" short:"e"   type:"path"`
 	IncludeContext         bool              `help:"Include the context in the rendered output as a resource of kind: Context."                                                                short:"c"`
-	FunctionCredentials    string            `help:"A YAML file or directory of YAML files specifying credentials to use for Functions to render the XR."                                      placeholder:"PATH" type:"path"`
+	FunctionCredentials    string            `help:"A YAML file or directory of YAML files specifying credentials to use for Functions to render the XR."                                      placeholder:"PATH" predictor:"yaml_file_or_directory" type:"path"`
 
 	Timeout time.Duration `default:"1m" help:"How long to run before timing out."`
 
diff --git a/cmd/crank/xpkg/build.go b/cmd/crank/xpkg/build.go
index 1442b9b42..5ce616719 100644
--- a/cmd/crank/xpkg/build.go
+++ b/cmd/crank/xpkg/build.go
@@ -95,11 +95,11 @@ func (c *buildCmd) AfterApply() error {
 type buildCmd struct {
 	// Flags. Keep sorted alphabetically.
 	EmbedRuntimeImage        string   `help:"An OCI image to embed in the package as its runtime."                                                                                                    placeholder:"NAME"                                                     xor:"runtime-image"`
-	EmbedRuntimeImageTarball string   `help:"An OCI image tarball to embed in the package as its runtime."                                                                                            placeholder:"PATH"                                                     type:"existingfile" xor:"runtime-image"`
-	ExamplesRoot             string   `default:"./examples"                                                                                                                                           help:"A directory of example YAML files to include in the package."    short:"e"           type:"path"`
+	EmbedRuntimeImageTarball string   `help:"An OCI image tarball to embed in the package as its runtime."                                                                                            placeholder:"PATH"                                                     predictor:"file"      type:"existingfile" xor:"runtime-image"`
+	ExamplesRoot             string   `default:"./examples"                                                                                                                                           help:"A directory of example YAML files to include in the package."    predictor:"directory" short:"e"           type:"path"`
 	Ignore                   []string `help:"Comma-separated file paths, specified relative to --package-root, to exclude from the package. Wildcards are supported. Directories cannot be excluded." placeholder:"PATH"`
-	PackageFile              string   `help:"The file to write the package to. Defaults to a generated filename in --package-root."                                                                   placeholder:"PATH"                                                     short:"o"           type:"path"`
-	PackageRoot              string   `default:"."                                                                                                                                                    help:"The directory that contains the package's crossplane.yaml file." short:"f"           type:"existingdir"`
+	PackageFile              string   `help:"The file to write the package to. Defaults to a generated filename in --package-root."                                                                   placeholder:"PATH"                                                     predictor:"xpkg_file" short:"o"           type:"path"`
+	PackageRoot              string   `default:"."                                                                                                                                                    help:"The directory that contains the package's crossplane.yaml file." predictor:"directory" short:"f"           type:"existingdir"`
 
 	// Internal state. These aren't part of the user-exposed CLI structure.
 	fs      afero.Fs
diff --git a/cmd/crank/xpkg/init.go b/cmd/crank/xpkg/init.go
index bbafaa9a3..9c026b4fc 100644
--- a/cmd/crank/xpkg/init.go
+++ b/cmd/crank/xpkg/init.go
@@ -56,7 +56,7 @@ type initCmd struct {
 	Name     string `arg:"" help:"The name of the new package to initialize."`
 	Template string `arg:"" help:"The template name or URL to use to initialize the new package."`
 
-	Directory     string `default:"."                                                     help:"The directory to initialize. It must be empty. It will be created if it doesn't exist." short:"d" type:"path"`
+	Directory     string `default:"."                                                     help:"The directory to initialize. It must be empty. It will be created if it doesn't exist." predictor:"directory" short:"d" type:"path"`
 	RunInitScript bool   `help:"Runs the init.sh script if it exists without prompting"   name:"run-init-script"                                                                        short:"r"`
 	RefName       string `help:"The branch or tag to clone from the template repository." name:"ref-name"                                                                               short:"b"`
 }
diff --git a/cmd/crank/xpkg/push.go b/cmd/crank/xpkg/push.go
index 47679ffca..c9435a813 100644
--- a/cmd/crank/xpkg/push.go
+++ b/cmd/crank/xpkg/push.go
@@ -63,7 +63,7 @@ type pushCmd struct {
 	Package string `arg:"" help:"Where to push the package."`
 
 	// Flags. Keep sorted alphabetically.
-	PackageFiles []string `help:"A comma-separated list of xpkg files to push." placeholder:"PATH" short:"f" type:"existingfile"`
+	PackageFiles []string `help:"A comma-separated list of xpkg files to push." placeholder:"PATH" predictor:"xpkg_file" short:"f" type:"existingfile"`
 
 	// Common Upbound API configuration.
 	upbound.Flags `embed:""`
diff --git a/cmd/crossplane/core/core.go b/cmd/crossplane/core/core.go
index a743a1f60..3452abff6 100644
--- a/cmd/crossplane/core/core.go
+++ b/cmd/crossplane/core/core.go
@@ -62,6 +62,7 @@ import (
 	"github.com/crossplane/crossplane/internal/validation/apiextensions/v1/composition"
 	"github.com/crossplane/crossplane/internal/validation/apiextensions/v1/xrd"
 	"github.com/crossplane/crossplane/internal/xfn"
+	"github.com/crossplane/crossplane/internal/xfn/cached"
 	"github.com/crossplane/crossplane/internal/xpkg"
 )
 
@@ -90,12 +91,13 @@ type startCommand struct {
 
 	Namespace      string `default:"crossplane-system"     env:"POD_NAMESPACE"                                                      help:"Namespace used to unpack and run packages."                         short:"n"`
 	ServiceAccount string `default:"crossplane"            env:"POD_SERVICE_ACCOUNT"                                                help:"Name of the Crossplane Service Account."`
-	CacheDir       string `default:"/cache"                env:"CACHE_DIR"                                                          help:"Directory used for caching package images."                         short:"c"`
 	LeaderElection bool   `default:"false"                 env:"LEADER_ELECTION"                                                    help:"Use leader election for the controller manager."                    short:"l"`
 	Registry       string `default:"${default_registry}"   env:"REGISTRY"                                                           help:"Default registry used to fetch packages when not specified in tag." short:"r"`
 	CABundlePath   string `env:"CA_BUNDLE_PATH"            help:"Additional CA bundle to use when fetching packages from registry."`
 	UserAgent      string `default:"${default_user_agent}" env:"USER_AGENT"                                                         help:"The User-Agent header that will be set on all package requests."`
 
+	XpkgCacheDir string `default:"/cache/xpkg" env:"XPKG_CACHE_DIR" help:"Directory used for caching package images."`
+
 	PackageRuntime string `default:"Deployment" env:"PACKAGE_RUNTIME" help:"The package runtime to use for packages with a runtime (e.g. Providers and Functions)"`
 
 	SyncInterval                     time.Duration `default:"1h"  help:"How often all resources will be double-checked for drift from the desired state."                      short:"s"`
@@ -103,8 +105,7 @@ type startCommand struct {
 	MaxReconcileRate                 int           `default:"100" help:"The global maximum rate per second at which resources may checked for drift from the desired state."`
 	MaxConcurrentPackageEstablishers int           `default:"10"  help:"The the maximum number of goroutines to use for establishing Providers, Configurations and Functions."`
 
-	WebhookEnabled                      bool `default:"true"  env:"WEBHOOK_ENABLED"                        help:"Enable webhook configuration."`
-	AutomaticDependencyDowngradeEnabled bool `default:"false" env:"AUTOMATIC_DEPENDENCY_DOWNGRADE_ENABLED" help:"Enable automatic dependency version downgrades. This configuration requires the 'EnableDependencyVersionUpgrades' feature flag to be enabled."`
+	WebhookEnabled bool `default:"true" env:"WEBHOOK_ENABLED" help:"Enable webhook configuration."`
 
 	WebhookPort     int `default:"9443" env:"WEBHOOK_PORT"      help:"The port the webhook server listens on."`
 	MetricsPort     int `default:"8080" env:"METRICS_PORT"      help:"The port the metrics server listens on."`
@@ -115,9 +116,14 @@ type startCommand struct {
 	TLSClientSecretName string `env:"TLS_CLIENT_SECRET_NAME" help:"The name of the TLS Secret that will be store Crossplane's client certificate."`
 	TLSClientCertsDir   string `env:"TLS_CLIENT_CERTS_DIR"   help:"The path of the folder which will store TLS client certificate of Crossplane."`
 
-	EnableExternalSecretStores      bool `group:"Alpha Features:" help:"Enable support for External Secret Stores."`
-	EnableDependencyVersionUpgrades bool `group:"Alpha Features:" help:"Enable support for upgrading dependency versions when the parent package is updated."`
-	EnableSignatureVerification     bool `group:"Alpha Features:" help:"Enable support for package signature verification via ImageConfig API."`
+	EnableExternalSecretStores        bool `group:"Alpha Features:" help:"Enable support for External Secret Stores."`
+	EnableDependencyVersionUpgrades   bool `group:"Alpha Features:" help:"Enable support for upgrading dependency versions when a dependent package is updated."`
+	EnableDependencyVersionDowngrades bool `group:"Alpha Features:" help:"Enable support for upgrading and downgrading dependency versions when a dependent package is updated."`
+	EnableSignatureVerification       bool `group:"Alpha Features:" help:"Enable support for package signature verification via ImageConfig API."`
+	EnableFunctionResponseCache       bool `group:"Alpha Features:" help:"Enable support for caching composition function responses."`
+
+	XfnCacheDir    string        `default:"/cache/xfn" env:"XFN_CACHE_DIR"     group:"Alpha Features:" help:"Directory used for caching function responses. Requires --enable-function-response-cache."`
+	XfnCacheMaxTTL time.Duration `default:"24h"        env:"XFN_CACHE_MAX_TTL" group:"Alpha Features:" help:"Maximum TTL for cached function responses. Set to 0 to disable. Requires --enable-function-response-cache."`
 
 	EnableCompositionWebhookSchemaValidation bool `default:"true" group:"Beta Features:" help:"Enable support for Composition validation using schemas."`
 	EnableDeploymentRuntimeConfigs           bool `default:"true" group:"Beta Features:" help:"Enable support for Deployment Runtime Configs."`
@@ -138,6 +144,9 @@ type startCommand struct {
 	// explicit and informative error on startup, instead of a potentially
 	// surprising one later.
 	EnableEnvironmentConfigs bool `hidden:""`
+
+	// Deprecated: Use XpkgCacheDir. Kept for backward compatibility.
+	CacheDir string `env:"CACHE_DIR" hidden:"" short:"c"`
 }
 
 // Run core Crossplane controllers.
@@ -229,6 +238,11 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 		log.Info("Extra Resources are GA and cannot be disabled. The --enable-composition-functions-extra-resources flag will be removed in a future release.")
 	}
 
+	if c.CacheDir != "" {
+		log.Info("The --cache-dir flag is deprecated and will be removed in a future release. Use --xpkg-cache-dir instead.")
+		c.XpkgCacheDir = c.CacheDir
+	}
+
 	// TODO(negz): Include a link to a migration guide.
 	if c.EnableEnvironmentConfigs {
 		//nolint:revive // This is long. It's easier to read with punctuation.
@@ -244,18 +258,39 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 		return errors.Wrap(err, "cannot load client TLS certificates")
 	}
 
-	xfnm := xfn.NewPrometheusMetrics()
-	metrics.Registry.MustRegister(xfnm)
+	pfrm := xfn.NewPrometheusMetrics()
+	metrics.Registry.MustRegister(pfrm)
 
 	// We want all XR controllers to share the same gRPC clients.
-	functionRunner := xfn.NewPackagedFunctionRunner(mgr.GetClient(),
+	pfr := xfn.NewPackagedFunctionRunner(mgr.GetClient(),
 		xfn.WithLogger(log),
 		xfn.WithTLSConfig(clienttls),
-		xfn.WithInterceptorCreators(xfnm),
+		xfn.WithInterceptorCreators(pfrm),
 	)
 
 	// Periodically remove clients for Functions that no longer exist.
-	go functionRunner.GarbageCollectConnections(ctx, 10*time.Minute)
+	go pfr.GarbageCollectConnections(ctx, 10*time.Minute)
+
+	var runner xfn.FunctionRunner = pfr
+
+	if c.EnableFunctionResponseCache {
+		o.Features.Enable(features.EnableAlphaFunctionResponseCache)
+		log.Info("Alpha feature enabled", "flag", features.EnableAlphaFunctionResponseCache)
+
+		cfrm := cached.NewPrometheusMetrics()
+		metrics.Registry.MustRegister(cfrm)
+
+		// Wrap the packaged function runner with a caching one.
+		cfr := cached.NewFileBackedRunner(pfr, c.XfnCacheDir,
+			cached.WithLogger(log),
+			cached.WithMetrics(cfrm),
+		)
+
+		// Periodically delete expired cache entries.
+		go cfr.GarbageCollectFiles(ctx, 1*time.Minute)
+
+		runner = cfr
+	}
 
 	if c.EnableCompositionWebhookSchemaValidation {
 		o.Features.Enable(features.EnableBetaCompositionWebhookSchemaValidation)
@@ -294,13 +329,14 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 		o.Features.Enable(features.EnableBetaClaimSSA)
 		log.Info("Beta feature enabled", "flag", features.EnableBetaClaimSSA)
 	}
-	if c.EnableDependencyVersionUpgrades {
+	// Enabling downgrades implicitly enables upgrades.
+	if c.EnableDependencyVersionUpgrades || c.EnableDependencyVersionDowngrades {
 		o.Features.Enable(features.EnableAlphaDependencyVersionUpgrades)
 		log.Info("Alpha feature enabled", "flag", features.EnableAlphaDependencyVersionUpgrades)
-
-		if c.AutomaticDependencyDowngradeEnabled {
-			log.Info("Automatic dependency downgrade is enabled.")
-		}
+	}
+	if c.EnableDependencyVersionDowngrades {
+		o.Features.Enable(features.EnableAlphaDependencyVersionDowngrades)
+		log.Info("Alpha feature enabled", "flag", features.EnableAlphaDependencyVersionDowngrades)
 	}
 	if c.EnableSignatureVerification {
 		o.Features.Enable(features.EnableAlphaSignatureVerification)
@@ -405,7 +441,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 	ao := apiextensionscontroller.Options{
 		Options:          o,
 		ControllerEngine: ce,
-		FunctionRunner:   functionRunner,
+		FunctionRunner:   runner,
 	}
 
 	if err := apiextensions.Setup(mgr, ao); err != nil {
@@ -424,15 +460,14 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 	}
 
 	po := pkgcontroller.Options{
-		Options:                             o,
-		Cache:                               xpkg.NewFsPackageCache(c.CacheDir, afero.NewOsFs()),
-		Namespace:                           c.Namespace,
-		ServiceAccount:                      c.ServiceAccount,
-		DefaultRegistry:                     c.Registry,
-		FetcherOptions:                      []xpkg.FetcherOpt{xpkg.WithUserAgent(c.UserAgent)},
-		PackageRuntime:                      pr,
-		MaxConcurrentPackageEstablishers:    c.MaxConcurrentPackageEstablishers,
-		AutomaticDependencyDowngradeEnabled: c.AutomaticDependencyDowngradeEnabled,
+		Options:                          o,
+		Cache:                            xpkg.NewFsPackageCache(c.XpkgCacheDir, afero.NewOsFs()),
+		Namespace:                        c.Namespace,
+		ServiceAccount:                   c.ServiceAccount,
+		DefaultRegistry:                  c.Registry,
+		FetcherOptions:                   []xpkg.FetcherOpt{xpkg.WithUserAgent(c.UserAgent)},
+		PackageRuntime:                   pr,
+		MaxConcurrentPackageEstablishers: c.MaxConcurrentPackageEstablishers,
 	}
 
 	// We need to set the TUF_ROOT environment variable so that the TUF client
@@ -443,7 +478,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
 	// ".sigstore/root" is coming from: https://github.com/sigstore/sigstore/blob/ecaaf75cf3a942cf224533ae15aee6eec19dc1e2/pkg/tuf/client.go#L558
 	// Check the following to read more about what TUF is and why it exists
 	// in this context: https://blog.sigstore.dev/the-update-framework-and-you-2f5cbaa964d5/
-	if err = os.Setenv("TUF_ROOT", filepath.Join(c.CacheDir, ".sigstore", "root")); err != nil {
+	if err = os.Setenv("TUF_ROOT", filepath.Join(c.XpkgCacheDir, ".sigstore", "root")); err != nil {
 		return errors.Wrap(err, "cannot set TUF_ROOT environment variable")
 	}
 
diff --git a/apis/generate.go b/generate.go
similarity index 50%
rename from apis/generate.go
rename to generate.go
index 345d7be63..c83b26452 100644
--- a/apis/generate.go
+++ b/generate.go
@@ -21,29 +21,29 @@ limitations under the License.
 // https://go.dev/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
 
 // Remove existing manifests
-//go:generate rm -rf ../cluster/crds
-//go:generate rm -rf ../cluster/webhookconfigurations/manifests.yaml
+//go:generate rm -rf ./cluster/crds
+//go:generate rm -rf ./cluster/webhookconfigurations/manifests.yaml
 
 // Replicate identical API versions
 
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1/composition_revision_types.go apiextensions/v1beta1
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1/composition_common.go apiextensions/v1beta1
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1/composition_patches.go apiextensions/v1beta1
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1/composition_transforms.go apiextensions/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1/composition_revision_types.go apis/apiextensions/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1/composition_common.go apis/apiextensions/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1/composition_patches.go apis/apiextensions/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1/composition_transforms.go apis/apiextensions/v1beta1
 
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1beta1/environment_config_types.go apiextensions/v1alpha1 false
-//go:generate ../hack/duplicate_api_type.sh apiextensions/v1beta1/usage_types.go apiextensions/v1alpha1 true
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1beta1/environment_config_types.go apis/apiextensions/v1alpha1 false
+//go:generate ./hack/duplicate_api_type.sh apis/apiextensions/v1beta1/usage_types.go apis/apiextensions/v1alpha1 true
 
-//go:generate ../hack/duplicate_api_type.sh pkg/v1/package_types.go pkg/v1beta1
-//go:generate ../hack/duplicate_api_type.sh pkg/v1/package_runtime_types.go pkg/v1beta1
-//go:generate ../hack/duplicate_api_type.sh pkg/v1/revision_types.go pkg/v1beta1
-//go:generate ../hack/duplicate_api_type.sh pkg/v1/function_types.go pkg/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/v1/package_types.go apis/pkg/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/v1/package_runtime_types.go apis/pkg/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/v1/revision_types.go apis/pkg/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/v1/function_types.go apis/pkg/v1beta1
 
-//go:generate ../hack/duplicate_api_type.sh pkg/meta/v1/configuration_types.go pkg/meta/v1alpha1
-//go:generate ../hack/duplicate_api_type.sh pkg/meta/v1/provider_types.go pkg/meta/v1alpha1
-//go:generate ../hack/duplicate_api_type.sh pkg/meta/v1/function_types.go pkg/meta/v1beta1
-//go:generate ../hack/duplicate_api_type.sh pkg/meta/v1/meta.go pkg/meta/v1alpha1
-//go:generate ../hack/duplicate_api_type.sh pkg/meta/v1/meta.go pkg/meta/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/meta/v1/configuration_types.go apis/pkg/meta/v1alpha1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/meta/v1/provider_types.go apis/pkg/meta/v1alpha1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/meta/v1/function_types.go apis/pkg/meta/v1beta1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/meta/v1/meta.go apis/pkg/meta/v1alpha1
+//go:generate ./hack/duplicate_api_type.sh apis/pkg/meta/v1/meta.go apis/pkg/meta/v1beta1
 
 // NOTE(negz): We generate deepcopy methods and CRDs for each API group
 // separately because there seems to be an undiagnosed bug in controller-runtime
@@ -51,25 +51,25 @@ limitations under the License.
 // generate them all together in one command.
 
 // Generate deepcopy methodsets and CRD manifests
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./pkg/v1alpha1;./pkg/v1beta1;./pkg/v1 crd:crdVersions=v1,generateEmbeddedObjectMeta=true output:artifacts:config=../cluster/crds
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./apiextensions/v1alpha1;./apiextensions/v1beta1;./apiextensions/v1 crd:crdVersions=v1 output:artifacts:config=../cluster/crds
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./secrets/... crd:crdVersions=v1 output:artifacts:config=../cluster/crds
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./apis/pkg/v1alpha1;./apis/pkg/v1beta1;./apis/pkg/v1 crd:crdVersions=v1,generateEmbeddedObjectMeta=true output:artifacts:config=./cluster/crds
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./apis/apiextensions/v1alpha1;./apis/apiextensions/v1beta1;./apis/apiextensions/v1 crd:crdVersions=v1 output:artifacts:config=./cluster/crds
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./apis/secrets/... crd:crdVersions=v1 output:artifacts:config=./cluster/crds
 
 // We generate the meta.pkg.crossplane.io types separately as the generated CRDs
 // are never installed, only used for API documentation.
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./pkg/meta/... crd:crdVersions=v1 output:artifacts:config=../cluster/meta
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./apis/pkg/meta/... crd:crdVersions=v1 output:artifacts:config=./cluster/meta
 
 // Generate webhook manifests
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen webhook paths=./pkg/v1alpha1;./pkg/v1beta1;./pkg/v1;./apiextensions/v1alpha1;./apiextensions/v1beta1;./apiextensions/v1 output:artifacts:config=../cluster/webhookconfigurations
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen webhook paths=./apis/pkg/v1alpha1;./apis/pkg/v1beta1;./apis/pkg/v1;./apis/apiextensions/v1alpha1;./apis/apiextensions/v1beta1;./apis/apiextensions/v1 output:artifacts:config=./cluster/webhookconfigurations
 
 // Generate conversion code
-//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./apiextensions/v1
-//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./pkg/meta/v1alpha1
-//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./pkg/meta/v1beta1
+//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./apis/apiextensions/v1
+//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./apis/pkg/meta/v1alpha1
+//go:generate go run -tags generate github.com/jmattheis/goverter/cmd/goverter gen -build-tags="" ./apis/pkg/meta/v1beta1
 
 // Replicate identical gRPC APIs
 
-//go:generate ../hack/duplicate_proto_type.sh apiextensions/fn/proto/v1/run_function.proto apiextensions/fn/proto/v1beta1
+//go:generate ./hack/duplicate_proto_type.sh apis/apiextensions/fn/proto/v1/run_function.proto apis/apiextensions/fn/proto/v1beta1
 
 // Generate gRPC types and stubs.
 //
@@ -85,7 +85,7 @@ limitations under the License.
 //go:generate go install google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
 //go:generate go run github.com/bufbuild/buf/cmd/buf@v1.53.0 generate
 
-package apis
+package generate
 
 import (
 	_ "github.com/jmattheis/goverter/cmd/goverter"      //nolint:typecheck
diff --git a/go.mod b/go.mod
index b23adab83..2f0e4644d 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	dario.cat/mergo v1.0.1
 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
 	github.com/Masterminds/semver v1.5.0
-	github.com/alecthomas/kong v0.9.0
+	github.com/alecthomas/kong v1.4.0
 	github.com/crossplane/crossplane-runtime v1.20.0-rc.0
 	github.com/docker/docker v27.1.1+incompatible
 	github.com/docker/go-connections v0.5.0
@@ -22,11 +22,13 @@ require (
 	github.com/in-toto/in-toto-golang v0.9.0
 	github.com/jmattheis/goverter v1.3.2
 	github.com/pkg/errors v0.9.1
+	github.com/posener/complete v1.2.3
 	github.com/sigstore/cosign/v2 v2.2.4
 	github.com/sigstore/sigstore v1.8.6
 	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/afero v1.11.0
 	github.com/upbound/up-sdk-go v0.1.1-0.20240122203953-2d00664aab8e
+	github.com/willabides/kongplete v0.4.0
 	golang.org/x/sync v0.12.0
 	google.golang.org/grpc v1.68.0
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
@@ -91,6 +93,8 @@ require (
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 	github.com/gorilla/websocket v1.5.1 // indirect
 	github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
+	github.com/hashicorp/errwrap v1.1.0 // indirect
+	github.com/hashicorp/go-multierror v1.1.1 // indirect
 	github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
 	github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect
 	github.com/hashicorp/go-sockaddr v1.0.6 // indirect
@@ -113,6 +117,7 @@ require (
 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
 	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
 	github.com/pjbgf/sha1cd v0.3.0 // indirect
+	github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
 	github.com/sagikazarmark/locafero v0.4.0 // indirect
 	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
 	github.com/sassoftware/relic v7.2.1+incompatible // indirect
diff --git a/go.sum b/go.sum
index bf1a467b6..524d1ad4b 100644
--- a/go.sum
+++ b/go.sum
@@ -83,10 +83,10 @@ github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY
 github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
 github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
 github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
-github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
-github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
-github.com/alecthomas/kong v0.9.0 h1:G5diXxc85KvoV2f0ZRVuMsi45IrBgx9zDNGNj165aPA=
-github.com/alecthomas/kong v0.9.0/go.mod h1:Y47y5gKfHp1hDc7CH7OeXgLIpp+Q2m1Ni0L5s3bI8Os=
+github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
+github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/kong v1.4.0 h1:UL7tzGMnnY0YRMMvJyITIRX1EpO6RbBRZDNcCevy3HA=
+github.com/alecthomas/kong v1.4.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
 github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
 github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
 github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
@@ -434,10 +434,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
 github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
 github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
 github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
@@ -594,6 +596,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
 github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
 github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -607,6 +611,8 @@ github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf h1:014O62
 github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY=
+github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E=
 github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -712,6 +718,8 @@ github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinC
 github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
 github.com/vladimirvivien/gexe v0.3.0 h1:4xwiOwGrDob5OMR6E92B9olDXYDglXdHhzR1ggYtWJM=
 github.com/vladimirvivien/gexe v0.3.0/go.mod h1:fp7cy60ON1xjhtEI/+bfSEIXX35qgmI+iRYlGOqbBFM=
+github.com/willabides/kongplete v0.4.0 h1:eivXxkp5ud5+4+NVN9e4goxC5mSh3n1RHov+gsblM2g=
+github.com/willabides/kongplete v0.4.0/go.mod h1:0P0jtWD9aTsqPSUAl4de35DLghrr57XcayPyvqSi2X8=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xanzy/go-gitlab v0.103.0 h1:J9pTQoq0GsEFqzd6srCM1QfdfKAxSNz6mT6ntrpNF2w=
diff --git a/internal/controller/apiextensions/composite/composition_functions.go b/internal/controller/apiextensions/composite/composition_functions.go
index e658999c9..80a464da2 100644
--- a/internal/controller/apiextensions/composite/composition_functions.go
+++ b/internal/controller/apiextensions/composite/composition_functions.go
@@ -18,12 +18,14 @@ package composite
 import (
 	"context"
 	"crypto/sha256"
+	"encoding/hex"
 	"fmt"
 	"sort"
 	"strings"
 	"time"
 
 	"google.golang.org/protobuf/encoding/protojson"
+	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/types/known/structpb"
 	corev1 "k8s.io/api/core/v1"
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
@@ -318,8 +320,8 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
 			}
 		}
 
-		// TODO(negz): Generate a content-addressable tag for this request.
-		// Perhaps using https://github.com/cerbos/protoc-gen-go-hashpb ?
+		req.Meta = &fnv1.RequestMeta{Tag: Tag(req)}
+
 		rsp, err := c.pipeline.RunFunction(ctx, fn.FunctionRef.Name, req)
 		if err != nil {
 			return CompositionResult{}, errors.Wrapf(err, errFmtRunPipelineStep, fn.Step)
@@ -575,6 +577,20 @@ func (c *FunctionComposer) Compose(ctx context.Context, xr *composite.Unstructur
 	return result, nil
 }
 
+// Tag uniquely identifies a request. Two identical requests created by the
+// same Crossplane binary will produce identical tags. Different builds of
+// Crossplane may produce different tags for the same inputs. See the docs for
+// the Deterministic protobuf MarshalOption for more details.
+func Tag(req *fnv1.RunFunctionRequest) string {
+	m := proto.MarshalOptions{Deterministic: true}
+	b, err := m.Marshal(req)
+	if err != nil {
+		return ""
+	}
+	h := sha256.Sum256(b)
+	return hex.EncodeToString(h[:])
+}
+
 // ComposedFieldOwnerName generates a unique field owner name
 // for a given Crossplane composite resource (XR). This uniqueness is crucial to
 // prevent multiple XRs, which compose the same resource, from continuously
diff --git a/internal/controller/apiextensions/controller/options.go b/internal/controller/apiextensions/controller/options.go
index f0fe3799b..3165e7886 100644
--- a/internal/controller/apiextensions/controller/options.go
+++ b/internal/controller/apiextensions/controller/options.go
@@ -32,5 +32,5 @@ type Options struct {
 	ControllerEngine *engine.ControllerEngine
 
 	// FunctionRunner used to run Composition Functions.
-	FunctionRunner *xfn.PackagedFunctionRunner
+	FunctionRunner xfn.FunctionRunner
 }
diff --git a/internal/controller/pkg/controller/options.go b/internal/controller/pkg/controller/options.go
index 7836d0eb9..46b3ccad1 100644
--- a/internal/controller/pkg/controller/options.go
+++ b/internal/controller/pkg/controller/options.go
@@ -49,8 +49,4 @@ type Options struct {
 	// MaxConcurrentPackageEstablishers is the maximum number of goroutines to use
 	// for establishing Providers, Configurations and Functions.
 	MaxConcurrentPackageEstablishers int
-
-	// AutomaticDependencyDowngradeEnabled is a configuration option that
-	// enables automatic downgrade of dependencies to the highest valid version.
-	AutomaticDependencyDowngradeEnabled bool
 }
diff --git a/internal/controller/pkg/resolver/reconciler.go b/internal/controller/pkg/resolver/reconciler.go
index 419010c5e..57949971b 100644
--- a/internal/controller/pkg/resolver/reconciler.go
+++ b/internal/controller/pkg/resolver/reconciler.go
@@ -181,7 +181,8 @@ func Setup(mgr ctrl.Manager, o controller.Options) error {
 
 	if o.Features.Enabled(features.EnableAlphaDependencyVersionUpgrades) {
 		opts = append(opts, WithNewDagFn(internaldag.NewUpgradingMapDag))
-		if o.AutomaticDependencyDowngradeEnabled {
+
+		if o.Features.Enabled(features.EnableAlphaDependencyVersionDowngrades) {
 			opts = append(opts, WithDowngradesEnabled())
 		}
 	}
diff --git a/internal/features/features.go b/internal/features/features.go
index e368d5e02..077b87a93 100644
--- a/internal/features/features.go
+++ b/internal/features/features.go
@@ -26,12 +26,23 @@ const (
 	// https://github.com/crossplane/crossplane/blob/390ddd/design/design-doc-external-secret-stores.md
 	EnableAlphaExternalSecretStores feature.Flag = "EnableAlphaExternalSecretStores"
 
-	// EnableAlphaDependencyVersionUpgrades enables alpha support for upgrading the version of a package's dependencies
-	// when needed.
+	// EnableAlphaDependencyVersionUpgrades enables alpha support for
+	// upgrading the version of a package's dependencies when needed.
 	EnableAlphaDependencyVersionUpgrades feature.Flag = "EnableAlphaDependencyVersionUpgrades"
 
-	// EnableAlphaSignatureVerification enables alpha support for verifying the package signatures via ImageConfig API.
+	// EnableAlphaDependencyVersionDowngrades enables alpha support for
+	// downgrading the version of a package's dependencies when needed.
+	// It builds on EnableAlphaDependencyVersionUpgrades; both flags must
+	// be set to enable downgrades.
+	EnableAlphaDependencyVersionDowngrades feature.Flag = "EnableAlphaDependencyVersionDowngrades"
+
+	// EnableAlphaSignatureVerification enables alpha support for verifying
+	// the package signatures via ImageConfig API.
 	EnableAlphaSignatureVerification feature.Flag = "EnableAlphaSignatureVerification"
+
+	// EnableAlphaFunctionResponseCache enables alpha support for caching
+	// composition function responses.
+	EnableAlphaFunctionResponseCache feature.Flag = "EnableAlphaFunctionResponseCache"
 )
 
 // Beta Feature Flags.
diff --git a/internal/xfn/cached/cached_runner.go b/internal/xfn/cached/cached_runner.go
new file mode 100644
index 000000000..c3a3def99
--- /dev/null
+++ b/internal/xfn/cached/cached_runner.go
@@ -0,0 +1,395 @@
+/*
+Copyright 2025 The Crossplane Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+*/
+
+// Package cached implements a cached function runner.
+package cached
+
+import (
+	"context"
+	"io/fs"
+	"path/filepath"
+	"time"
+
+	"github.com/spf13/afero"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/types/known/timestamppb"
+
+	"github.com/crossplane/crossplane-runtime/pkg/errors"
+	"github.com/crossplane/crossplane-runtime/pkg/logging"
+
+	fnv1 "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1"
+	"github.com/crossplane/crossplane/internal/xfn/cached/proto/v1alpha1"
+)
+
+// A CacheMissReason indicates what caused a cache miss.
+type CacheMissReason string
+
+// Cache miss reasons.
+const (
+	ReasonNotCached       CacheMissReason = "NotCached"
+	ReasonDeadlineExpired CacheMissReason = "DeadlineExpired"
+	ReasonEmptyRequestTag CacheMissReason = "EmptyRequestTag"
+	ReasonError           CacheMissReason = "Error"
+)
+
+// Metrics for the function response cache.
+type Metrics interface { //nolint:interfacebloat // Only a little bit bloated. :|
+	// Hit records a cache hit.
+	Hit(name string)
+
+	// Miss records a cache miss.
+	Miss(name string)
+
+	// Error records a cache error.
+	Error(name string)
+
+	// Write records a cache write.
+	Write(name string)
+
+	// Delete records a cache delete, i.e. due to garbage collection.
+	Delete(name string)
+
+	// WroteBytes records bytes written to the cache.
+	WroteBytes(name string, b int)
+
+	// DeletedBytes records bytes deleted from the cache.
+	DeletedBytes(name string, b int)
+
+	// ReadDuration records the time taken by a cache hit.
+	ReadDuration(name string, d time.Duration)
+
+	// WriteDuration records the time taken to write to cache.
+	WriteDuration(name string, d time.Duration)
+}
+
+// A FunctionRunner runs a composition function.
+type FunctionRunner interface {
+	// RunFunction runs the named composition function.
+	RunFunction(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error)
+}
+
+// A FileBackedRunner wraps another function runner. It caches responses
+// returned by that runner to the filesystem. It only caches responses that
+// specify a TTL. Requests are served from cache if there's a cached response
+// for an identical request with an unexpired TTL.
+type FileBackedRunner struct {
+	wrapped FunctionRunner
+	fs      afero.Afero
+	maxTTL  time.Duration
+	log     logging.Logger
+	metrics Metrics
+}
+
+// A FileBackedRunnerOption configures a FileBackedRunner.
+type FileBackedRunnerOption func(r *FileBackedRunner)
+
+// WithLogger specifies which logger the FileBackedRunner should use.
+func WithLogger(l logging.Logger) FileBackedRunnerOption {
+	return func(r *FileBackedRunner) {
+		r.log = l
+	}
+}
+
+// WithMetrics specifies which metrics the FileBackedRunner should use.
+func WithMetrics(m Metrics) FileBackedRunnerOption {
+	return func(r *FileBackedRunner) {
+		r.metrics = m
+	}
+}
+
+// WithMaxTTL clamps the maximum TTL for cached responses. The maximum TTL will
+// be used to set the cache deadline for any response with a TTL greater than
+// the max.
+func WithMaxTTL(ttl time.Duration) FileBackedRunnerOption {
+	return func(r *FileBackedRunner) {
+		r.maxTTL = ttl
+	}
+}
+
+// WithFilesystem specifies which filesystem implementation the FileBackedRunner
+// should use. The runner will ignore its path argument and cache files at the
+// root of this filesystem. Wrap your desired filesystem with afero.BasePathFS
+// to cache files under a specific path.
+func WithFilesystem(fs afero.Fs) FileBackedRunnerOption {
+	return func(r *FileBackedRunner) {
+		r.fs = afero.Afero{Fs: fs}
+	}
+}
+
+// NewFileBackedRunner creates a new function runner that wraps another runner,
+// caching its responses to the filesystem.
+func NewFileBackedRunner(wrap FunctionRunner, path string, o ...FileBackedRunnerOption) *FileBackedRunner {
+	r := &FileBackedRunner{
+		wrapped: wrap,
+		fs:      afero.Afero{Fs: afero.NewBasePathFs(afero.NewOsFs(), path)},
+		log:     logging.NewNopLogger(),
+		metrics: &NopMetrics{},
+	}
+
+	for _, fn := range o {
+		fn(r)
+	}
+
+	return r
+}
+
+// RunFunction tries to return a response from cache. It falls back to calling
+// the wrapped runner.
+func (r *FileBackedRunner) RunFunction(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+	start := time.Now()
+	log := r.log.WithValues("name", name)
+
+	// If we don't have a cache key we can't perform a cache lookup, or
+	// cache the response. Just send it on. This should never happen.
+	if req.GetMeta().GetTag() == "" {
+		log.Debug("RunFunctionResponse cache miss", "reason", ReasonEmptyRequestTag)
+		r.metrics.Miss(name)
+		return r.wrapped.RunFunction(ctx, name, req)
+	}
+
+	key := filepath.Join(name, req.GetMeta().GetTag())
+	log = log.WithValues("cache-key", key)
+
+	b, err := r.fs.ReadFile(key)
+	if errors.Is(err, fs.ErrNotExist) {
+		log.Debug("RunFunctionResponse cache miss", "reason", ReasonNotCached)
+		r.metrics.Miss(name)
+		return r.CacheFunction(ctx, name, req)
+	}
+	if err != nil {
+		log.Info("RunFunctionResponse cache miss", "reason", ReasonError, "err", err)
+		r.metrics.Miss(name)
+		r.metrics.Error(name)
+		return r.CacheFunction(ctx, name, req)
+	}
+
+	crsp := &v1alpha1.CachedRunFunctionResponse{}
+	if err := proto.Unmarshal(b, crsp); err != nil {
+		log.Info("RunFunctionResponse cache miss", "reason", ReasonError, "err", err)
+		r.metrics.Miss(name)
+		r.metrics.Error(name)
+		return r.CacheFunction(ctx, name, req)
+	}
+
+	deadline := crsp.GetDeadline().AsTime()
+
+	// Cached response has expired. This also covers the case where the
+	// deadline isn't set - e.g. because we unmarshaled an empty file.
+	if time.Now().After(deadline) {
+		log.Debug("RunFunctionResponse cache miss", "reason", ReasonDeadlineExpired, "deadline", deadline)
+		r.metrics.Miss(name)
+		return r.CacheFunction(ctx, name, req)
+	}
+
+	log.Debug("RunFunctionResponse cache hit")
+	r.metrics.Hit(name)
+	r.metrics.ReadDuration(name, time.Since(start))
+	return crsp.GetResponse(), nil
+}
+
+// CacheFunction runs a function and caches its response if the TTL is non-zero.
+func (r *FileBackedRunner) CacheFunction(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+	// If we don't have a cache key we can't cache the response. Just send
+	// it on. This should never happen.
+	if req.GetMeta().GetTag() == "" {
+		return r.wrapped.RunFunction(ctx, name, req)
+	}
+
+	key := filepath.Join(name, req.GetMeta().GetTag())
+	log := r.log.WithValues("name", name, "cache-key", key)
+
+	rsp, err := r.wrapped.RunFunction(ctx, name, req)
+	if err != nil {
+		return rsp, err
+	}
+
+	// Start timing the cache write _after_ we make the request.
+	start := time.Now()
+
+	ttl := rsp.GetMeta().GetTtl().AsDuration()
+	if ttl == 0 {
+		return rsp, nil
+	}
+
+	// Clamp the TTL to the allowed maximum, if set.
+	if r.maxTTL > 0 && ttl > r.maxTTL {
+		log.Debug("RunFunctionResponse cache clamped response TTL", "requested-ttl", ttl, "clamped-ttl", r.maxTTL)
+		ttl = r.maxTTL
+	}
+
+	// Not all filesystems have btime, and Go doesn't expose a simple
+	// interface to get it. So instead of adding TTL to btime at cache read
+	// time, we instead compute a deadline at write time and wrap the cached
+	// response.
+	deadline := time.Now().Add(ttl)
+	msg, err := proto.Marshal(&v1alpha1.CachedRunFunctionResponse{Deadline: timestamppb.New(deadline), Response: rsp})
+	if err != nil {
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+
+	if err := r.fs.MkdirAll(name, 0o700); err != nil {
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+
+	// Write and rename a temp file to make our write 'atomic'. This ensure
+	// we won't overwrite a cache file that we're currently reading.
+	tmp, err := r.fs.TempFile(name, "")
+	if err != nil {
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+	if _, err := tmp.Write(msg); err != nil {
+		_ = tmp.Close()
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+	if err := tmp.Close(); err != nil {
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+	if err := r.fs.Rename(tmp.Name(), key); err != nil {
+		log.Info("RunFunctionResponse cache write error", "err", err)
+		r.metrics.Error(name)
+		return rsp, nil
+	}
+
+	log.Debug("RunFunctionResponse cache write", "deadline", deadline, "bytes", len(msg))
+	r.metrics.Write(name)
+	r.metrics.WriteDuration(name, time.Since(start))
+	r.metrics.WroteBytes(name, len(msg))
+	return rsp, nil
+}
+
+// GarbageCollectFiles runs every interval until the supplied context is
+// cancelled. It garbage collects cached responses with expired deadlines.
+func (r *FileBackedRunner) GarbageCollectFiles(ctx context.Context, interval time.Duration) {
+	t := time.NewTicker(interval)
+	defer t.Stop()
+
+	for {
+		select {
+		case <-ctx.Done():
+			r.log.Debug("Stopping RunFunctionResponse cache garbage collector", "error", ctx.Err())
+			return
+		case <-t.C:
+			if _, err := r.GarbageCollectFilesNow(ctx); err != nil {
+				r.log.Info("Cannot garbage collect cached RunFunctionResponses", "error", err)
+			}
+		}
+	}
+}
+
+// GarbageCollectFilesNow immediately garbage collects any cached responses with
+// expired deadlines.
+func (r *FileBackedRunner) GarbageCollectFilesNow(ctx context.Context) (int, error) {
+	collected := 0
+	iofs := afero.NewIOFS(r.fs)
+	err := fs.WalkDir(iofs, "/", func(path string, d fs.DirEntry, err error) error {
+		if err != nil {
+			return err
+		}
+
+		// Stop walking if our context is cancelled.
+		select {
+		case <-ctx.Done():
+			return nil
+		default:
+		}
+
+		if d.IsDir() {
+			// Don't try to garbage collect the root of the cache.
+			if path == "/" {
+				return nil
+			}
+
+			entries, err := r.fs.ReadDir(path)
+			if err != nil {
+				r.log.Info("RunFunctionResponse cache error", "path", path, "error", err)
+				return nil
+			}
+
+			if len(entries) > 0 {
+				return nil
+			}
+
+			// Cleanup empty directories. We don't count these as a
+			// garbage collected cache entry.
+			if err := r.fs.Remove(path); err != nil {
+				r.log.Info("RunFunctionResponse cache error", "path", path, "error", err)
+			}
+			return nil
+		}
+
+		// The cache layout is like /cache/function-name/request-hash,
+		// so the directory name is our function name.
+		name := filepath.Base(filepath.Dir(path))
+		log := r.log.WithValues("name", name, "cache-key", path)
+
+		b, err := r.fs.ReadFile(path)
+		if err != nil {
+			log.Info("RunFunctionResponse cache error", "error", err)
+			r.metrics.Error(name)
+			return nil
+		}
+
+		crsp := &v1alpha1.CachedRunFunctionResponse{}
+		if err := proto.Unmarshal(b, crsp); err != nil {
+			log.Info("RunFunctionResponse cache error", "error", err)
+			r.metrics.Error(name)
+			return nil
+		}
+
+		deadline := crsp.GetDeadline().AsTime()
+
+		// Cached response is still valid.
+		if time.Now().Before(deadline) {
+			return nil
+		}
+
+		info, err := d.Info()
+		if err != nil {
+			log.Info("RunFunctionResponse cache error", "error", err)
+			r.metrics.Error(name)
+		}
+
+		// There's a race here. It's possible CacheFunction will write a
+		// new cache entry with a deadline in the future between where
+		// we read the file and here where we remove it. We're okay with
+		// this - it'll just mean we don't cache one response.
+		//
+		// There's no race with reading files. The file content won't
+		// actually be deleted until ReadFile closes the fd.
+		if err := r.fs.Remove(path); err != nil {
+			log.Info("RunFunctionResponse cache error", "error", err)
+			r.metrics.Error(name)
+			return nil
+		}
+
+		collected++
+		log.Debug("RunFunctionResponse cache delete", "deadline", deadline, "bytes", info.Size())
+		r.metrics.Delete(name)
+		r.metrics.DeletedBytes(name, int(info.Size()))
+		return nil
+	})
+
+	return collected, err
+}
diff --git a/internal/xfn/cached/cached_runner_metrics.go b/internal/xfn/cached/cached_runner_metrics.go
new file mode 100644
index 000000000..7acffad52
--- /dev/null
+++ b/internal/xfn/cached/cached_runner_metrics.go
@@ -0,0 +1,209 @@
+/*
+Copyright 2025 The Crossplane Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+*/
+
+package cached
+
+import (
+	"time"
+
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+	_ Metrics = &NopMetrics{}
+	_ Metrics = &PrometheusMetrics{}
+)
+
+// NopMetrics does nothing.
+type NopMetrics struct{}
+
+// Hit does nothing.
+func (m *NopMetrics) Hit(_ string) {}
+
+// Miss does nothing.
+func (m *NopMetrics) Miss(_ string) {}
+
+// Error does nothing.
+func (m *NopMetrics) Error(_ string) {}
+
+// Write does nothing.
+func (m *NopMetrics) Write(_ string) {}
+
+// Delete does nothing.
+func (m *NopMetrics) Delete(_ string) {}
+
+// WroteBytes does nothing.
+func (m *NopMetrics) WroteBytes(_ string, _ int) {}
+
+// DeletedBytes does nothing.
+func (m *NopMetrics) DeletedBytes(_ string, _ int) {}
+
+// ReadDuration does nothing.
+func (m *NopMetrics) ReadDuration(_ string, _ time.Duration) {}
+
+// WriteDuration does nothing.
+func (m *NopMetrics) WriteDuration(_ string, _ time.Duration) {}
+
+// PrometheusMetrics for the function response cache.
+type PrometheusMetrics struct {
+	hits   *prometheus.CounterVec
+	misses *prometheus.CounterVec
+	errors *prometheus.CounterVec
+
+	writes  *prometheus.CounterVec
+	deletes *prometheus.CounterVec
+
+	bytesWritten *prometheus.CounterVec
+	bytesDeleted *prometheus.CounterVec
+
+	readDuration  *prometheus.HistogramVec
+	writeDuration *prometheus.HistogramVec
+}
+
+// NewPrometheusMetrics exposes function response cache metrics via Prometheus.
+func NewPrometheusMetrics() *PrometheusMetrics {
+	return &PrometheusMetrics{
+		hits: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_hits_total",
+			Help:      "Total number of RunFunctionResponse cache hits.",
+		}, []string{"function_name"}),
+
+		misses: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_misses_total",
+			Help:      "Total number of RunFunctionResponse cache misses.",
+		}, []string{"function_name"}),
+
+		errors: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_errors_total",
+			Help:      "Total number of RunFunctionResponse cache errors.",
+		}, []string{"function_name"}),
+
+		writes: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_writes_total",
+			Help:      "Total number of RunFunctionResponses cache writes.",
+		}, []string{"function_name"}),
+
+		deletes: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_deletes_total",
+			Help:      "Total number of RunFunctionResponses cache deletes.",
+		}, []string{"function_name"}),
+
+		bytesWritten: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_bytes_written_total",
+			Help:      "Total number of RunFunctionResponse bytes written.",
+		}, []string{"function_name"}),
+
+		bytesDeleted: prometheus.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_bytes_deleted_total",
+			Help:      "Total number of RunFunctionResponse bytes deleted.",
+		}, []string{"function_name"}),
+
+		readDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_read_seconds",
+			Help:      "Histogram of RunFunctionResponse cache read time (seconds).",
+			Buckets:   prometheus.DefBuckets,
+		}, []string{"function_name"}),
+
+		writeDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{
+			Subsystem: "composition",
+			Name:      "run_function_response_cache_write_seconds",
+			Help:      "Histogram of RunFunctionResponse cache write time (seconds).",
+			Buckets:   prometheus.DefBuckets,
+		}, []string{"function_name"}),
+	}
+}
+
+// Hit records a cache hit.
+func (m *PrometheusMetrics) Hit(name string) {
+	m.hits.With(prometheus.Labels{"function_name": name}).Inc()
+}
+
+// Miss records a cache miss.
+func (m *PrometheusMetrics) Miss(name string) {
+	m.misses.With(prometheus.Labels{"function_name": name}).Inc()
+}
+
+// Error records a cache error.
+func (m *PrometheusMetrics) Error(name string) {
+	m.errors.With(prometheus.Labels{"function_name": name}).Inc()
+}
+
+// Write records a cache write.
+func (m *PrometheusMetrics) Write(name string) {
+	m.writes.With(prometheus.Labels{"function_name": name}).Inc()
+}
+
+// Delete records a cache delete, i.e. due to garbage collection.
+func (m *PrometheusMetrics) Delete(name string) {
+	m.deletes.With(prometheus.Labels{"function_name": name}).Inc()
+}
+
+// WroteBytes records bytes written from the cache.
+func (m *PrometheusMetrics) WroteBytes(name string, b int) {
+	m.bytesWritten.With(prometheus.Labels{"function_name": name}).Add(float64(b))
+}
+
+// DeletedBytes records bytes deleted from the cache.
+func (m *PrometheusMetrics) DeletedBytes(name string, b int) {
+	m.bytesDeleted.With(prometheus.Labels{"function_name": name}).Add(float64(b))
+}
+
+// ReadDuration records the time taken by a cache hit.
+func (m *PrometheusMetrics) ReadDuration(name string, d time.Duration) {
+	m.readDuration.With(prometheus.Labels{"function_name": name}).Observe(d.Seconds())
+}
+
+// WriteDuration records the time taken to write to cache.
+func (m *PrometheusMetrics) WriteDuration(name string, d time.Duration) {
+	m.writeDuration.With(prometheus.Labels{"function_name": name}).Observe(d.Seconds())
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector to the provided channel and returns once
+// the last descriptor has been sent.
+func (m *PrometheusMetrics) Describe(ch chan<- *prometheus.Desc) {
+	m.hits.Describe(ch)
+	m.misses.Describe(ch)
+	m.errors.Describe(ch)
+	m.writes.Describe(ch)
+	m.deletes.Describe(ch)
+	m.bytesWritten.Describe(ch)
+	m.bytesDeleted.Describe(ch)
+	m.readDuration.Describe(ch)
+	m.writeDuration.Describe(ch)
+}
+
+// Collect is called by the Prometheus registry when collecting
+// metrics. The implementation sends each collected metric via the
+// provided channel and returns once the last metric has been sent.
+func (m *PrometheusMetrics) Collect(ch chan<- prometheus.Metric) {
+	m.hits.Collect(ch)
+	m.misses.Collect(ch)
+	m.errors.Collect(ch)
+	m.writes.Collect(ch)
+	m.deletes.Collect(ch)
+	m.bytesWritten.Collect(ch)
+	m.bytesDeleted.Collect(ch)
+	m.readDuration.Collect(ch)
+	m.writeDuration.Collect(ch)
+}
diff --git a/internal/xfn/cached/proto/v1alpha1/cached_response.pb.go b/internal/xfn/cached/proto/v1alpha1/cached_response.pb.go
new file mode 100644
index 000000000..4a81f1518
--- /dev/null
+++ b/internal/xfn/cached/proto/v1alpha1/cached_response.pb.go
@@ -0,0 +1,180 @@
+//
+//Copyright 2025 The Crossplane Authors.
+//
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.35.2
+// 	protoc        (unknown)
+// source: internal/xfn/cached/proto/v1alpha1/cached_response.proto
+
+package v1alpha1
+
+import (
+	v1 "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// A CachedRunFunctionResponse is Crossplane's on-disk cache format for a
+// RunFunctionResponse.
+type CachedRunFunctionResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Deadline after which the cached response is no longer valid.
+	Deadline *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=deadline,proto3" json:"deadline,omitempty"`
+	// The cached response.
+	Response *v1.RunFunctionResponse `protobuf:"bytes,2,opt,name=response,proto3" json:"response,omitempty"`
+}
+
+func (x *CachedRunFunctionResponse) Reset() {
+	*x = CachedRunFunctionResponse{}
+	mi := &file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_msgTypes[0]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *CachedRunFunctionResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CachedRunFunctionResponse) ProtoMessage() {}
+
+func (x *CachedRunFunctionResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_msgTypes[0]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use CachedRunFunctionResponse.ProtoReflect.Descriptor instead.
+func (*CachedRunFunctionResponse) Descriptor() ([]byte, []int) {
+	return file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CachedRunFunctionResponse) GetDeadline() *timestamppb.Timestamp {
+	if x != nil {
+		return x.Deadline
+	}
+	return nil
+}
+
+func (x *CachedRunFunctionResponse) GetResponse() *v1.RunFunctionResponse {
+	if x != nil {
+		return x.Response
+	}
+	return nil
+}
+
+var File_internal_xfn_cached_proto_v1alpha1_cached_response_proto protoreflect.FileDescriptor
+
+var file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDesc = []byte{
+	0x0a, 0x38, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x78, 0x66, 0x6e, 0x2f, 0x63,
+	0x61, 0x63, 0x68, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x61, 0x6c,
+	0x70, 0x68, 0x61, 0x31, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 0x69, 0x6e, 0x74, 0x65,
+	0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x78, 0x66, 0x6e, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x31,
+	0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+	0x6e, 0x73, 0x2f, 0x66, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x72,
+	0x75, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x22, 0x9f, 0x01, 0x0a, 0x19, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x52, 0x75, 0x6e,
+	0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x36, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08,
+	0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61, 0x70, 0x69,
+	0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x66, 0x6e, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69,
+	0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x63, 0x72,
+	0x6f, 0x73, 0x73, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
+	0x6c, 0x2f, 0x78, 0x66, 0x6e, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
+}
+
+var (
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescOnce sync.Once
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescData = file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDesc
+)
+
+func file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescGZIP() []byte {
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescOnce.Do(func() {
+		file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescData)
+	})
+	return file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDescData
+}
+
+var file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_goTypes = []any{
+	(*CachedRunFunctionResponse)(nil), // 0: internal.xfn.cached.proto.v1alpha1.CachedRunFunctionResponse
+	(*timestamppb.Timestamp)(nil),     // 1: google.protobuf.Timestamp
+	(*v1.RunFunctionResponse)(nil),    // 2: apiextensions.fn.proto.v1.RunFunctionResponse
+}
+var file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_depIdxs = []int32{
+	1, // 0: internal.xfn.cached.proto.v1alpha1.CachedRunFunctionResponse.deadline:type_name -> google.protobuf.Timestamp
+	2, // 1: internal.xfn.cached.proto.v1alpha1.CachedRunFunctionResponse.response:type_name -> apiextensions.fn.proto.v1.RunFunctionResponse
+	2, // [2:2] is the sub-list for method output_type
+	2, // [2:2] is the sub-list for method input_type
+	2, // [2:2] is the sub-list for extension type_name
+	2, // [2:2] is the sub-list for extension extendee
+	0, // [0:2] is the sub-list for field type_name
+}
+
+func init() { file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_init() }
+func file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_init() {
+	if File_internal_xfn_cached_proto_v1alpha1_cached_response_proto != nil {
+		return
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_goTypes,
+		DependencyIndexes: file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_depIdxs,
+		MessageInfos:      file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_msgTypes,
+	}.Build()
+	File_internal_xfn_cached_proto_v1alpha1_cached_response_proto = out.File
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_rawDesc = nil
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_goTypes = nil
+	file_internal_xfn_cached_proto_v1alpha1_cached_response_proto_depIdxs = nil
+}
diff --git a/internal/xfn/cached/proto/v1alpha1/cached_response.proto b/internal/xfn/cached/proto/v1alpha1/cached_response.proto
new file mode 100644
index 000000000..e19b88f71
--- /dev/null
+++ b/internal/xfn/cached/proto/v1alpha1/cached_response.proto
@@ -0,0 +1,34 @@
+/*
+   Copyright 2025 The Crossplane Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+syntax = "proto3";
+
+package internal.xfn.cached.proto.v1alpha1;
+
+import "apis/apiextensions/fn/proto/v1/run_function.proto";
+import "google/protobuf/timestamp.proto";
+
+option go_package = "github.com/crossplane/crossplane/internal/xfn/cached/proto/v1alpha1";
+
+// A CachedRunFunctionResponse is Crossplane's on-disk cache format for a
+// RunFunctionResponse.
+message CachedRunFunctionResponse {
+  // Deadline after which the cached response is no longer valid.
+  google.protobuf.Timestamp deadline = 1;
+
+  // The cached response.
+  apiextensions.fn.proto.v1.RunFunctionResponse response = 2;
+}
diff --git a/internal/xfn/function_runner.go b/internal/xfn/function_runner.go
index 511bac607..9ff124d39 100644
--- a/internal/xfn/function_runner.go
+++ b/internal/xfn/function_runner.go
@@ -73,6 +73,12 @@ const svcConfig = `
 	]
 }`
 
+// A FunctionRunner runs a composition function.
+type FunctionRunner interface {
+	// RunFunction runs the named composition function.
+	RunFunction(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error)
+}
+
 // A PackagedFunctionRunner runs a Function by making a gRPC call to a Function
 // package's runtime. It creates a gRPC client connection for each Function. The
 // Function's endpoint is determined by reading the status.endpoint of the
diff --git a/internal/xpkg/upbound/context.go b/internal/xpkg/upbound/context.go
index b9fdb1b80..2e3ab7f85 100644
--- a/internal/xpkg/upbound/context.go
+++ b/internal/xpkg/upbound/context.go
@@ -59,7 +59,7 @@ type Flags struct {
 	Account               string   `env:"UP_ACCOUNT"                  help:"Account used to execute command."            json:"account,omitempty"               short:"a"`
 	Domain                *url.URL `default:"https://upbound.io"      env:"UP_DOMAIN"                                    help:"Root Upbound domain."            json:"domain,omitempty"`
 	InsecureSkipTLSVerify bool     `env:"UP_INSECURE_SKIP_TLS_VERIFY" help:"[INSECURE] Skip verifying TLS certificates." json:"insecureSkipTLSVerify,omitempty"`
-	Profile               string   `env:"UP_PROFILE"                  help:"Profile used to execute command."            json:"profile,omitempty"               predictor:"profiles"`
+	Profile               string   `env:"UP_PROFILE"                  help:"Profile used to execute command."            json:"profile,omitempty"`
 
 	// Hidden flags.
 	APIEndpoint      *url.URL `env:"OVERRIDE_API_ENDPOINT"      help:"Overrides the default API endpoint."      hidden:"" json:"apiEndpoint,omitempty"      name:"override-api-endpoint"`



Test patch:
diff --git a/internal/xfn/cached/cached_runner_test.go b/internal/xfn/cached/cached_runner_test.go
new file mode 100644
index 000000000..84e5ba568
--- /dev/null
+++ b/internal/xfn/cached/cached_runner_test.go
@@ -0,0 +1,428 @@
+/*
+Copyright 2025 The Crossplane Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed
+under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+CONDITIONS OF ANY KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+*/
+
+package cached
+
+import (
+	"bytes"
+	"context"
+	"errors"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"github.com/spf13/afero"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/testing/protocmp"
+	"google.golang.org/protobuf/types/known/durationpb"
+	"google.golang.org/protobuf/types/known/timestamppb"
+
+	"github.com/crossplane/crossplane-runtime/pkg/logging"
+
+	fnv1 "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1"
+	"github.com/crossplane/crossplane/internal/xfn/cached/proto/v1alpha1"
+)
+
+type FunctionRunnerFn func(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error)
+
+func (fn FunctionRunnerFn) RunFunction(ctx context.Context, name string, req *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+	return fn(ctx, name, req)
+}
+
+var MockDir = []byte("DIR")
+
+func MockFs(files map[string][]byte) afero.Fs {
+	fs := afero.NewMemMapFs()
+	for path, data := range files {
+		// Special value for making a directory.
+		if bytes.Equal(data, MockDir) {
+			if err := fs.MkdirAll(path, 0o700); err != nil {
+				panic(err)
+			}
+			continue
+		}
+		if err := afero.WriteFile(fs, path, data, 0o600); err != nil {
+			panic(err)
+		}
+	}
+	return fs
+}
+
+var _ logging.Logger = &TestLogger{}
+
+type TestLogger struct {
+	t   *testing.T
+	kvs []any
+}
+
+func (l *TestLogger) Info(msg string, keysAndValues ...any) {
+	l.t.Logf("INFO: %s (%s)", msg, append(l.kvs, keysAndValues...))
+}
+
+func (l *TestLogger) Debug(msg string, keysAndValues ...any) {
+	l.t.Logf("DEBUG: %s (%s)", msg, append(l.kvs, keysAndValues...))
+}
+
+func (l *TestLogger) WithValues(keysAndValues ...any) logging.Logger {
+	l.kvs = append(l.kvs, keysAndValues...)
+	return l
+}
+
+func TestRunFunction(t *testing.T) {
+	type params struct {
+		wrap FunctionRunner
+		path string
+		o    []FileBackedRunnerOption
+	}
+	type args struct {
+		ctx  context.Context
+		name string
+		req  *fnv1.RunFunctionRequest
+	}
+	type want struct {
+		rsp *fnv1.RunFunctionResponse
+		err error
+	}
+
+	cases := map[string]struct {
+		reason string
+		params params
+		args   args
+		want   want
+	}{
+		"MissingTag": {
+			reason: "If the request is missing a tag we should call the wrapped runner without caching.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					rsp := &fnv1.RunFunctionResponse{
+						Meta: &fnv1.ResponseMeta{Tag: "hi"},
+					}
+					return rsp, nil
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(afero.NewMemMapFs()),
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{Tag: "hi"},
+				},
+			},
+		},
+		"NotCached": {
+			reason: "If the response isn't cached we should call the wrapped runner and cache it.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					rsp := &fnv1.RunFunctionResponse{
+						Meta: &fnv1.ResponseMeta{
+							Tag: "hello",
+							Ttl: durationpb.New(10 * time.Minute),
+						},
+					}
+					return rsp, nil
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(afero.NewMemMapFs()),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{
+						Tag: "hello",
+						Ttl: durationpb.New(10 * time.Minute),
+					},
+				},
+			},
+		},
+		"WrappedError": {
+			reason: "If the response isn't cached and the wrapped runner returns an error we should return it.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					return nil, errors.New("boom")
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(afero.NewMemMapFs()),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				err: cmpopts.AnyError,
+			},
+		},
+		"EmptyFile": {
+			reason: "If the cached response is empty should call the wrapped runner and cache it.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					rsp := &fnv1.RunFunctionResponse{
+						Meta: &fnv1.ResponseMeta{
+							Tag: "hello",
+							Ttl: durationpb.New(10 * time.Minute),
+						},
+					}
+					return rsp, nil
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(MockFs(map[string][]byte{
+						"coolfn/hello": {},
+					})),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{
+						Tag: "hello",
+						Ttl: durationpb.New(10 * time.Minute),
+					},
+				},
+			},
+		},
+		"UnexpectedFile": {
+			reason: "If the cached response contains unexpected data we should call the wrapped runner and cache it.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					rsp := &fnv1.RunFunctionResponse{
+						Meta: &fnv1.ResponseMeta{
+							Tag: "hello",
+							Ttl: durationpb.New(10 * time.Minute),
+						},
+					}
+					return rsp, nil
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(MockFs(map[string][]byte{
+						"coolfn/hello": []byte("Hello dearest caller. I'm not a deadline followed by an encoded RunFunctionResponse."),
+					})),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{
+						Tag: "hello",
+						Ttl: durationpb.New(10 * time.Minute),
+					},
+				},
+			},
+		},
+		"DeadlineExceeded": {
+			reason: "If the cached response's deadline has passed we should call the wrapped runner and cache it.",
+			params: params{
+				wrap: FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+					rsp := &fnv1.RunFunctionResponse{
+						Meta: &fnv1.ResponseMeta{
+							Tag: "hello",
+							Ttl: durationpb.New(10 * time.Minute),
+						},
+					}
+					return rsp, nil
+				}),
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(MockFs(map[string][]byte{
+						"coolfn/hello": func() []byte {
+							msg, _ := proto.Marshal(&v1alpha1.CachedRunFunctionResponse{
+								// In the past.
+								Deadline: timestamppb.New(time.Now().Add(-1 * time.Minute)),
+								Response: &fnv1.RunFunctionResponse{
+									Meta: &fnv1.ResponseMeta{
+										Tag: "exceeded",
+										Ttl: durationpb.New(10 * time.Minute),
+									},
+								},
+							})
+
+							return msg
+						}(),
+					})),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{
+						Tag: "hello",
+						Ttl: durationpb.New(10 * time.Minute),
+					},
+				},
+			},
+		},
+		"CacheHit": {
+			reason: "If the cached response is still valid, return it without calling the wrapped runner.",
+			params: params{
+				// Wrap is nil. It'd panic if called.
+				o: []FileBackedRunnerOption{
+					WithLogger(&TestLogger{t: t}),
+					WithFilesystem(MockFs(map[string][]byte{
+						"coolfn/hello": func() []byte {
+							msg, _ := proto.Marshal(&v1alpha1.CachedRunFunctionResponse{
+								Deadline: timestamppb.New(time.Now().Add(1 * time.Minute)),
+								Response: &fnv1.RunFunctionResponse{
+									Meta: &fnv1.ResponseMeta{
+										Tag: "hello",
+										Ttl: durationpb.New(10 * time.Minute),
+									},
+								},
+							})
+
+							return msg
+						}(),
+					})),
+				},
+			},
+			args: args{
+				name: "coolfn",
+				req: &fnv1.RunFunctionRequest{
+					Meta: &fnv1.RequestMeta{Tag: "hello"},
+				},
+			},
+			want: want{
+				rsp: &fnv1.RunFunctionResponse{
+					Meta: &fnv1.ResponseMeta{
+						Tag: "hello",
+						Ttl: durationpb.New(10 * time.Minute),
+					},
+				},
+			},
+		},
+	}
+
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+			r := NewFileBackedRunner(tc.params.wrap, tc.params.path, tc.params.o...)
+			rsp, err := r.RunFunction(tc.args.ctx, tc.args.name, tc.args.req)
+
+			if diff := cmp.Diff(tc.want.rsp, rsp, protocmp.Transform()); diff != "" {
+				t.Errorf("\n%s\nr.RunFunction(...): -want rsp, +got rsp:\n%s", tc.reason, diff)
+			}
+
+			if diff := cmp.Diff(tc.want.err, err, cmpopts.EquateErrors()); diff != "" {
+				t.Errorf("\n%s\nr.RunFunction(...): -want err, +got err:\n%s", tc.reason, diff)
+			}
+		})
+	}
+}
+
+// We test through to CacheFunction a lot in TestRunFunction. This is just a
+// little sanity check to make sure we can actually read back what we write.
+func TestCacheFunction(t *testing.T) {
+	rsp := &fnv1.RunFunctionResponse{
+		Meta: &fnv1.ResponseMeta{
+			Tag: "wrapped",
+			Ttl: durationpb.New(1 * time.Minute),
+		},
+	}
+
+	wrapped := FunctionRunnerFn(func(_ context.Context, _ string, _ *fnv1.RunFunctionRequest) (*fnv1.RunFunctionResponse, error) {
+		return rsp, nil
+	})
+
+	fs := afero.NewMemMapFs()
+
+	r := NewFileBackedRunner(wrapped, "/cache",
+		WithLogger(&TestLogger{t: t}),
+		WithFilesystem(fs))
+
+	// Populate the cache.
+	got, err := r.CacheFunction(context.TODO(), "coolfn", &fnv1.RunFunctionRequest{Meta: &fnv1.RequestMeta{Tag: "req"}})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if diff := cmp.Diff(rsp, got, protocmp.Transform()); diff != "" {
+		t.Errorf("\nr.RunFunction(...): -want rsp, +got rsp:\n%s", diff)
+	}
+
+	// Create a new runner backed by the same populated cache, but with a
+	// nil wrapped runner that would panic if called.
+	r = NewFileBackedRunner(nil, "/cache",
+		WithLogger(&TestLogger{t: t}),
+		WithFilesystem(fs))
+
+	// Make sure we can read back what we just wrote.
+	got, err = r.RunFunction(context.TODO(), "coolfn", &fnv1.RunFunctionRequest{Meta: &fnv1.RequestMeta{Tag: "req"}})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if diff := cmp.Diff(rsp, got, protocmp.Transform()); diff != "" {
+		t.Errorf("\nr.RunFunction(...): -want rsp, +got rsp:\n%s", diff)
+	}
+}
+
+func TestGarbageCollectFilesNow(t *testing.T) {
+	// Deadline in the past.
+	past, _ := proto.Marshal(&v1alpha1.CachedRunFunctionResponse{Deadline: timestamppb.New(time.Now().Add(-1 * time.Minute))})
+
+	// Deadline in the future.
+	future, _ := proto.Marshal(&v1alpha1.CachedRunFunctionResponse{Deadline: timestamppb.New(time.Now().Add(1 * time.Minute))})
+
+	fs := MockFs(map[string][]byte{
+		"/":                         MockDir,
+		"/coolfn":                   MockDir,
+		"/coolfn/expired":           past,
+		"/coolfn/valid":             future,
+		"/coolfn/alsovalid":         future,
+		"/prettycoolfn":             MockDir,
+		"/prettycoolfn/expired":     past,
+		"/prettycoolfn/alsoexpired": past,
+	})
+
+	r := NewFileBackedRunner(nil, "/cache",
+		WithLogger(&TestLogger{t: t}),
+		WithFilesystem(fs))
+
+	collected, err := r.GarbageCollectFilesNow(context.TODO())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	want := 3
+	if diff := cmp.Diff(want, collected); diff != "" {
+		t.Errorf("\nr.GarbageCollectFilesNow(...): -want collected, +got collected:\n%s", diff)
+	}
+}
diff --git a/test/e2e/apiextensions_test.go b/test/e2e/apiextensions_test.go
index d793ad751..036534ddd 100644
--- a/test/e2e/apiextensions_test.go
+++ b/test/e2e/apiextensions_test.go
@@ -38,6 +38,22 @@ import (
 // extensions (i.e. Composition, XRDs, etc).
 const LabelAreaAPIExtensions = "apiextensions"
 
+// Tests that should be part of the test suite for the alpha function response
+// caching feature. There's no special tests for this; we just run the regular
+// test suite with caching enabled.
+const SuiteFunctionResponseCache = "function-response-cache"
+
+func init() {
+	environment.AddTestSuite(SuiteFunctionResponseCache,
+		config.WithHelmInstallOpts(
+			helm.WithArgs("--set args={--debug,--enable-function-response-cache}"),
+		),
+		config.WithLabelsToSelect(features.Labels{
+			config.LabelTestSuite: []string{SuiteFunctionResponseCache, config.TestSuiteDefault},
+		}),
+	)
+}
+
 var nopList = composed.NewList(composed.FromReferenceToList(corev1.ObjectReference{
 	APIVersion: "nop.crossplane.io/v1alpha1",
 	Kind:       "NopResource",
diff --git a/test/e2e/pkg_test.go b/test/e2e/pkg_test.go
index 8d2bff078..cdd6eda20 100644
--- a/test/e2e/pkg_test.go
+++ b/test/e2e/pkg_test.go
@@ -53,10 +53,7 @@ const (
 func init() {
 	environment.AddTestSuite(SuitePackageDependencyUpdates,
 		config.WithHelmInstallOpts(
-			helm.WithArgs("--set args={--debug,--enable-dependency-version-upgrades}"),
-		),
-		config.WithHelmInstallOpts(
-			helm.WithArgs("--set packageManager.enableAutomaticDependencyDowngrade=\"true\""),
+			helm.WithArgs("--set args={--debug,--enable-dependency-version-upgrades,--enable-dependency-version-downgrades}"),
 		),
 		config.WithLabelsToSelect(features.Labels{
 			config.LabelTestSuite: []string{SuitePackageDependencyUpdates, config.TestSuiteDefault},