Repository: deislabs/ratify
Pull request #664 (2023-02-21 10:20:39)

feat: bump up CRD version to v1beta1
# Description

## What this PR does / why we need it:
Update CRD version from v1alpha1 to v1beta1.

Basically I followed this [example](https://github.com/Azure/eraser/pull/544), [API conversion guide](https://cluster-api-ibmcloud.sigs.k8s.io/developer/conversion.html) and this [example](https://github.com/kubernetes-sigs/kubebuilder/issues/1529#issuecomment-656359330) to make the upgrade. For the hub-spoke conversion code, I use [conversion-gen](https://pkg.go.dev/k8s.io/code-generator/cmd/conversion-gen) to auto-generate it.

Added a doc listing the steps of the upgrade.

Steps for the upgrade:
1. Create new APIs version by: `kubebuilder create api --group config.ratify.deislabs.io --version v1beta1 --kind <kind>`
2. Copy over existing types.
3. Create an unversioned API which will become the hub between `v1alpha1` and `v1beta1` to faciliate conversion. When we add a new V1 version, it would be convenient to generate conversion functions between `v1` and `unversioned`.
4. Copy over existing types to unversioned API.
5. In each "spoke" version package(v1alpha1, v1beta1), add marker `+k8s:conversion-gen` directive pointing to the “hub” version package. It must be in doc.go.
6. In “spoke” version package, add a `localSchemeBuilder = runtime.NewSchemeBuilder(SchemeBuilder.AddToScheme)` in `groupversion_info.go` so the auto-generated code would compile. 
7. In unversioned package, create doc.go file and add marker: ` +kubebuilder:object:generate=true`
8. Add `+kubebuilder:skip` to `unversioned` api.
9. Mark `v1beta1` as the storage version, add marker `+kubebuilder:storageversion` to `v1beta1`.
10. run `make manifests generate` to generate CRD objects, DeepCopy and conversion methods.

Notes:
in this pr, we didn't make any changes to the CRD properties. In the future, if we have incompatible changes, we would have to Add `{kind}_conversion.go` in each version to implement `Convertible` for each type.

## Which issue(s) this PR fixes *(optional, using `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when the PR gets merged)*:
Fixes https://github.com/deislabs/ratify/issues/602

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Test passed. Tested locally with v1alpha1 CR as well.

# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [ ] Do all new files have appropriate license header?


codecov[bot]: # [Codecov](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
Base: **43.13**% // Head: **43.13**% // No change to project coverage :thumbsup:
> Coverage data is based on head [(`0e8f912`)](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) compared to base [(`eddcc9d`)](https://codecov.io/gh/deislabs/ratify/commit/eddcc9db69cb68ee8d29b8d41b287103a262288e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).
> Patch coverage: 45.45% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main     #664   +/-   ##
=======================================
  Coverage   43.13%   43.13%           
=======================================
  Files          56       56           
  Lines        3276     3276           
=======================================
  Hits         1413     1413           
  Misses       1715     1715           
  Partials      148      148           
```


| [Impacted Files](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [pkg/controllers/certificatestore\_controller.go](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXJzL2NlcnRpZmljYXRlc3RvcmVfY29udHJvbGxlci5nbw==) | `12.50% <33.33%> (ø)` | |
| [pkg/controllers/store\_controller.go](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXJzL3N0b3JlX2NvbnRyb2xsZXIuZ28=) | `35.59% <50.00%> (ø)` | |
| [pkg/controllers/verifier\_controller.go](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NvbnRyb2xsZXJzL3ZlcmlmaWVyX2NvbnRyb2xsZXIuZ28=) | `37.09% <50.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/deislabs/ratify/pull/664?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).

sozercan: instead of this being a breaking change, you should consider creating a seperate v1beta1 api and converting between different versions https://book.kubebuilder.io/multiversion-tutorial/tutorial.html
example: https://github.com/Azure/eraser/pull/544

Patch:
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index f81d0ce..aeefe87 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -91,10 +91,10 @@ jobs:
       - name: Save logs
         if: ${{ always() }}
         run: |
-          kubectl logs -n gatekeeper-system -l control-plane=controller-manager --tail=-1 > logs-externaldata-controller.json
-          kubectl logs -n gatekeeper-system -l control-plane=audit-controller --tail=-1 > logs-externaldata-audit.json
-          kubectl logs -n gatekeeper-system -l app=ratify --tail=-1 > logs-ratify-preinstall.json
-          kubectl logs -n gatekeeper-system -l app.kubernetes.io/name=ratify --tail=-1 > logs-ratify.json
+          kubectl logs -n gatekeeper-system -l control-plane=controller-manager --tail=-1 > logs-externaldata-controller-${{ matrix.KUBERNETES_VERSION }}-${{ matrix.GATEKEEPER_VERSION }}.json
+          kubectl logs -n gatekeeper-system -l control-plane=audit-controller --tail=-1 > logs-externaldata-audit-${{ matrix.KUBERNETES_VERSION }}-${{ matrix.GATEKEEPER_VERSION }}.json
+          kubectl logs -n gatekeeper-system -l app=ratify --tail=-1 > logs-ratify-preinstall-${{ matrix.KUBERNETES_VERSION }}-${{ matrix.GATEKEEPER_VERSION }}.json
+          kubectl logs -n gatekeeper-system -l app.kubernetes.io/name=ratify --tail=-1 > logs-ratify-${{ matrix.KUBERNETES_VERSION }}-${{ matrix.GATEKEEPER_VERSION }}.json
       - name: Upload artifacts
         uses: actions/upload-artifact@v3
         if: ${{ always() }}
diff --git a/Makefile b/Makefile
index e80ccc9..127765a 100644
--- a/Makefile
+++ b/Makefile
@@ -413,8 +413,12 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
 	$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
 
 .PHONY: generate
-generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
+generate: controller-gen conversion-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. Also generate conversions between structs of different API versions.
 	$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
+	$(CONVERSION_GEN) \
+        --input-dirs "./api/v1beta1,./api/v1alpha1" \
+        --go-header-file "./hack/boilerplate.go.txt" \
+        --output-file-base "zz_generated.conversion"
 
 .PHONY: fmt
 fmt: ## Run go fmt against code.
@@ -458,10 +462,12 @@ $(LOCALBIN):
 KUSTOMIZE ?= $(LOCALBIN)/kustomize
 CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
 ENVTEST ?= $(LOCALBIN)/setup-envtest
+CONVERSION_GEN ?= $(LOCALBIN)/conversion-gen
 
 ## Tool Versions
 KUSTOMIZE_VERSION ?= v3.8.7
 CONTROLLER_TOOLS_VERSION ?= v0.9.2
+CONVERSION_TOOLS_VERSION ?= v0.26.1
 
 KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
 .PHONY: kustomize
@@ -473,3 +479,8 @@ $(KUSTOMIZE): $(LOCALBIN)
 controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
 $(CONTROLLER_GEN): $(LOCALBIN)
 	test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
+
+.PHONY: conversion-gen
+conversion-gen: $(CONVERSION_GEN) ## Download conversion-gen locally if necessary.
+$(CONVERSION_GEN): $(LOCALBIN)
+	test -s $(LOCALBIN)/conversion-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/conversion-gen@$(CONVERSION_TOOLS_VERSION)
diff --git a/PROJECT b/PROJECT
index 9ff0e08..2800397 100644
--- a/PROJECT
+++ b/PROJECT
@@ -31,4 +31,31 @@ resources:
   kind: CertificateStore
   path: github.com/deislabs/ratify/api/v1alpha1
   version: v1alpha1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: ratify.deislabs.io
+  group: config
+  kind: Verifier
+  path: github.com/deislabs/ratify/api/v1beta1
+  version: v1beta1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: ratify.deislabs.io
+  group: config
+  kind: Store
+  path: github.com/deislabs/ratify/api/v1beta1
+  version: v1beta1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: ratify.deislabs.io
+  group: config
+  kind: CertificateStore
+  path: github.com/deislabs/ratify/api/v1beta1
+  version: v1beta1
 version: "3"
diff --git a/api/group.go b/api/group.go
new file mode 100644
index 0000000..8cc67e5
--- /dev/null
+++ b/api/group.go
@@ -0,0 +1,16 @@
+/*
+Copyright The Ratify 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 apis
diff --git a/api/unversioned/common.go b/api/unversioned/common.go
new file mode 100644
index 0000000..00e3024
--- /dev/null
+++ b/api/unversioned/common.go
@@ -0,0 +1,31 @@
+/*
+Copyright The Ratify 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 unversioned
+
+import runtime "k8s.io/apimachinery/pkg/runtime"
+
+// PluginSource defines the fields needed to download a plugin from an OCI Artifact source
+type PluginSource struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// OCI Artifact source to download the plugin from
+	Artifact string `json:"artifact,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// AuthProvider to use to authenticate to the OCI Artifact source, optional
+	AuthProvider runtime.RawExtension `json:"authProvider,omitempty"`
+}
diff --git a/api/unversioned/doc.go b/api/unversioned/doc.go
new file mode 100644
index 0000000..ef32ea5
--- /dev/null
+++ b/api/unversioned/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright The Ratify 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 unversioned
+
+// +kubebuilder:object:generate=true
diff --git a/api/unversioned/store_types.go b/api/unversioned/store_types.go
new file mode 100644
index 0000000..52971dd
--- /dev/null
+++ b/api/unversioned/store_types.go
@@ -0,0 +1,59 @@
+/*
+Copyright The Ratify 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.
+*/
+
+// +kubebuilder:skip
+package unversioned
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// StoreSpec defines the desired state of Store
+type StoreSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the store
+	Name string `json:"name,omitempty"`
+	// Plugin path, optional
+	Address string `json:"address,omitempty"`
+	// OCI Artifact source to download the plugin from, optional
+	Source *PluginSource `json:"source,omitempty"`
+
+	// Parameters of the store
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// StoreStatus defines the observed state of Store
+type StoreStatus struct {
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// Store is the Schema for the stores API
+type Store struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   StoreSpec   `json:"spec,omitempty"`
+	Status StoreStatus `json:"status,omitempty"`
+}
+
+// StoreList contains a list of Store
+type StoreList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Store `json:"items"`
+}
diff --git a/api/unversioned/verifier_types.go b/api/unversioned/verifier_types.go
new file mode 100644
index 0000000..e559257
--- /dev/null
+++ b/api/unversioned/verifier_types.go
@@ -0,0 +1,65 @@
+/*
+Copyright The Ratify 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.
+*/
+
+// +kubebuilder:skip
+package unversioned
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// VerifierSpec defines the desired state of Verifier
+type VerifierSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the verifier
+	Name string `json:"name,omitempty"`
+
+	// The type of artifact this verifier handles
+	ArtifactTypes string `json:"artifactTypes,omitempty"`
+
+	// # Optional. URL/file path
+	Address string `json:"address,omitempty"`
+
+	// OCI Artifact source to download the plugin from, optional
+	Source *PluginSource `json:"source,omitempty"`
+
+	// Parameters for this verifier
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// VerifierStatus defines the observed state of Verifier
+type VerifierStatus struct {
+	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// Verifier is the Schema for the verifiers API
+type Verifier struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   VerifierSpec   `json:"spec,omitempty"`
+	Status VerifierStatus `json:"status,omitempty"`
+}
+
+// VerifierList contains a list of Verifier
+type VerifierList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Verifier `json:"items"`
+}
diff --git a/api/unversioned/zz_generated.deepcopy.go b/api/unversioned/zz_generated.deepcopy.go
new file mode 100644
index 0000000..53cd091
--- /dev/null
+++ b/api/unversioned/zz_generated.deepcopy.go
@@ -0,0 +1,272 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright The Ratify 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 controller-gen. DO NOT EDIT.
+
+package unversioned
+
+import ()
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStore) DeepCopyInto(out *CertificateStore) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStore.
+func (in *CertificateStore) DeepCopy() *CertificateStore {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStore)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreList) DeepCopyInto(out *CertificateStoreList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]CertificateStore, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreList.
+func (in *CertificateStoreList) DeepCopy() *CertificateStoreList {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreSpec) DeepCopyInto(out *CertificateStoreSpec) {
+	*out = *in
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreSpec.
+func (in *CertificateStoreSpec) DeepCopy() *CertificateStoreSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreStatus) DeepCopyInto(out *CertificateStoreStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreStatus.
+func (in *CertificateStoreStatus) DeepCopy() *CertificateStoreStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PluginSource) DeepCopyInto(out *PluginSource) {
+	*out = *in
+	in.AuthProvider.DeepCopyInto(&out.AuthProvider)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginSource.
+func (in *PluginSource) DeepCopy() *PluginSource {
+	if in == nil {
+		return nil
+	}
+	out := new(PluginSource)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Store) DeepCopyInto(out *Store) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Store.
+func (in *Store) DeepCopy() *Store {
+	if in == nil {
+		return nil
+	}
+	out := new(Store)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreList) DeepCopyInto(out *StoreList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Store, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreList.
+func (in *StoreList) DeepCopy() *StoreList {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreSpec) DeepCopyInto(out *StoreSpec) {
+	*out = *in
+	if in.Source != nil {
+		in, out := &in.Source, &out.Source
+		*out = new(PluginSource)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreSpec.
+func (in *StoreSpec) DeepCopy() *StoreSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreStatus) DeepCopyInto(out *StoreStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreStatus.
+func (in *StoreStatus) DeepCopy() *StoreStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Verifier) DeepCopyInto(out *Verifier) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Verifier.
+func (in *Verifier) DeepCopy() *Verifier {
+	if in == nil {
+		return nil
+	}
+	out := new(Verifier)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierList) DeepCopyInto(out *VerifierList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Verifier, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierList.
+func (in *VerifierList) DeepCopy() *VerifierList {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierSpec) DeepCopyInto(out *VerifierSpec) {
+	*out = *in
+	if in.Source != nil {
+		in, out := &in.Source, &out.Source
+		*out = new(PluginSource)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierSpec.
+func (in *VerifierSpec) DeepCopy() *VerifierSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierStatus) DeepCopyInto(out *VerifierStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierStatus.
+func (in *VerifierStatus) DeepCopy() *VerifierStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierStatus)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go
index 0808c56..f0212b6 100644
--- a/api/v1alpha1/common.go
+++ b/api/v1alpha1/common.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/api/v1alpha1/doc.go b/api/v1alpha1/doc.go
new file mode 100644
index 0000000..5f12afe
--- /dev/null
+++ b/api/v1alpha1/doc.go
@@ -0,0 +1,18 @@
+/*
+Copyright The Ratify 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.
+*/
+
+// +k8s:conversion-gen=github.com/deislabs/ratify/api/unversioned
+package v1alpha1
diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go
index 9eba5a2..008b602 100644
--- a/api/v1alpha1/groupversion_info.go
+++ b/api/v1alpha1/groupversion_info.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ limitations under the License.
 package v1alpha1
 
 import (
+	runtime "k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"sigs.k8s.io/controller-runtime/pkg/scheme"
 )
@@ -33,4 +34,6 @@ var (
 
 	// AddToScheme adds the types in this group-version to the given scheme.
 	AddToScheme = SchemeBuilder.AddToScheme
+
+	localSchemeBuilder = runtime.NewSchemeBuilder(SchemeBuilder.AddToScheme)
 )
diff --git a/api/v1alpha1/store_types.go b/api/v1alpha1/store_types.go
index 4d37950..0e5b57a 100644
--- a/api/v1alpha1/store_types.go
+++ b/api/v1alpha1/store_types.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ type StoreStatus struct {
 
 // +kubebuilder:object:root=true
 // +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:deprecatedversion:warning="v1alpha1 of the Store API has been deprecated. Please migrate to v1beta1."
 
 // Store is the Schema for the stores API
 type Store struct {
diff --git a/api/v1alpha1/verifier_types.go b/api/v1alpha1/verifier_types.go
index 07fc456..ecfc1da 100644
--- a/api/v1alpha1/verifier_types.go
+++ b/api/v1alpha1/verifier_types.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@ type VerifierStatus struct {
 
 // +kubebuilder:object:root=true
 // +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:deprecatedversion:warning="v1alpha1 of the Verifier API has been deprecated. Please migrate to v1beta1."
 
 // Verifier is the Schema for the verifiers API
 type Verifier struct {
diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go
new file mode 100644
index 0000000..e994749
--- /dev/null
+++ b/api/v1alpha1/zz_generated.conversion.go
@@ -0,0 +1,483 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright The Ratify 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 conversion-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	unsafe "unsafe"
+
+	unversioned "github.com/deislabs/ratify/api/unversioned"
+	conversion "k8s.io/apimachinery/pkg/conversion"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+func init() {
+	localSchemeBuilder.Register(RegisterConversions)
+}
+
+// RegisterConversions adds conversion functions to the given scheme.
+// Public to allow building arbitrary schemes.
+func RegisterConversions(s *runtime.Scheme) error {
+	if err := s.AddGeneratedConversionFunc((*CertificateStore)(nil), (*unversioned.CertificateStore)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_CertificateStore_To_unversioned_CertificateStore(a.(*CertificateStore), b.(*unversioned.CertificateStore), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStore)(nil), (*CertificateStore)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStore_To_v1alpha1_CertificateStore(a.(*unversioned.CertificateStore), b.(*CertificateStore), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreList)(nil), (*unversioned.CertificateStoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_CertificateStoreList_To_unversioned_CertificateStoreList(a.(*CertificateStoreList), b.(*unversioned.CertificateStoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreList)(nil), (*CertificateStoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreList_To_v1alpha1_CertificateStoreList(a.(*unversioned.CertificateStoreList), b.(*CertificateStoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreSpec)(nil), (*unversioned.CertificateStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(a.(*CertificateStoreSpec), b.(*unversioned.CertificateStoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreSpec)(nil), (*CertificateStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec(a.(*unversioned.CertificateStoreSpec), b.(*CertificateStoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreStatus)(nil), (*unversioned.CertificateStoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(a.(*CertificateStoreStatus), b.(*unversioned.CertificateStoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreStatus)(nil), (*CertificateStoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus(a.(*unversioned.CertificateStoreStatus), b.(*CertificateStoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*PluginSource)(nil), (*unversioned.PluginSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_PluginSource_To_unversioned_PluginSource(a.(*PluginSource), b.(*unversioned.PluginSource), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.PluginSource)(nil), (*PluginSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_PluginSource_To_v1alpha1_PluginSource(a.(*unversioned.PluginSource), b.(*PluginSource), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*Store)(nil), (*unversioned.Store)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_Store_To_unversioned_Store(a.(*Store), b.(*unversioned.Store), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.Store)(nil), (*Store)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_Store_To_v1alpha1_Store(a.(*unversioned.Store), b.(*Store), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreList)(nil), (*unversioned.StoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_StoreList_To_unversioned_StoreList(a.(*StoreList), b.(*unversioned.StoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreList)(nil), (*StoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreList_To_v1alpha1_StoreList(a.(*unversioned.StoreList), b.(*StoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreSpec)(nil), (*unversioned.StoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(a.(*StoreSpec), b.(*unversioned.StoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreSpec)(nil), (*StoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec(a.(*unversioned.StoreSpec), b.(*StoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreStatus)(nil), (*unversioned.StoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_StoreStatus_To_unversioned_StoreStatus(a.(*StoreStatus), b.(*unversioned.StoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreStatus)(nil), (*StoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreStatus_To_v1alpha1_StoreStatus(a.(*unversioned.StoreStatus), b.(*StoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*Verifier)(nil), (*unversioned.Verifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_Verifier_To_unversioned_Verifier(a.(*Verifier), b.(*unversioned.Verifier), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.Verifier)(nil), (*Verifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_Verifier_To_v1alpha1_Verifier(a.(*unversioned.Verifier), b.(*Verifier), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierList)(nil), (*unversioned.VerifierList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_VerifierList_To_unversioned_VerifierList(a.(*VerifierList), b.(*unversioned.VerifierList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierList)(nil), (*VerifierList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierList_To_v1alpha1_VerifierList(a.(*unversioned.VerifierList), b.(*VerifierList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierSpec)(nil), (*unversioned.VerifierSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(a.(*VerifierSpec), b.(*unversioned.VerifierSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierSpec)(nil), (*VerifierSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(a.(*unversioned.VerifierSpec), b.(*VerifierSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierStatus)(nil), (*unversioned.VerifierStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus(a.(*VerifierStatus), b.(*unversioned.VerifierStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierStatus)(nil), (*VerifierStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus(a.(*unversioned.VerifierStatus), b.(*VerifierStatus), scope)
+	}); err != nil {
+		return err
+	}
+	return nil
+}
+
+func autoConvert_v1alpha1_CertificateStore_To_unversioned_CertificateStore(in *CertificateStore, out *unversioned.CertificateStore, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1alpha1_CertificateStore_To_unversioned_CertificateStore is an autogenerated conversion function.
+func Convert_v1alpha1_CertificateStore_To_unversioned_CertificateStore(in *CertificateStore, out *unversioned.CertificateStore, s conversion.Scope) error {
+	return autoConvert_v1alpha1_CertificateStore_To_unversioned_CertificateStore(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStore_To_v1alpha1_CertificateStore(in *unversioned.CertificateStore, out *CertificateStore, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_CertificateStore_To_v1alpha1_CertificateStore is an autogenerated conversion function.
+func Convert_unversioned_CertificateStore_To_v1alpha1_CertificateStore(in *unversioned.CertificateStore, out *CertificateStore, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStore_To_v1alpha1_CertificateStore(in, out, s)
+}
+
+func autoConvert_v1alpha1_CertificateStoreList_To_unversioned_CertificateStoreList(in *CertificateStoreList, out *unversioned.CertificateStoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.CertificateStore)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1alpha1_CertificateStoreList_To_unversioned_CertificateStoreList is an autogenerated conversion function.
+func Convert_v1alpha1_CertificateStoreList_To_unversioned_CertificateStoreList(in *CertificateStoreList, out *unversioned.CertificateStoreList, s conversion.Scope) error {
+	return autoConvert_v1alpha1_CertificateStoreList_To_unversioned_CertificateStoreList(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreList_To_v1alpha1_CertificateStoreList(in *unversioned.CertificateStoreList, out *CertificateStoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]CertificateStore)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreList_To_v1alpha1_CertificateStoreList is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreList_To_v1alpha1_CertificateStoreList(in *unversioned.CertificateStoreList, out *CertificateStoreList, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreList_To_v1alpha1_CertificateStoreList(in, out, s)
+}
+
+func autoConvert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in *CertificateStoreSpec, out *unversioned.CertificateStoreSpec, s conversion.Scope) error {
+	out.Provider = in.Provider
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec is an autogenerated conversion function.
+func Convert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in *CertificateStoreSpec, out *unversioned.CertificateStoreSpec, s conversion.Scope) error {
+	return autoConvert_v1alpha1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec(in *unversioned.CertificateStoreSpec, out *CertificateStoreSpec, s conversion.Scope) error {
+	out.Provider = in.Provider
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec(in *unversioned.CertificateStoreSpec, out *CertificateStoreSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreSpec_To_v1alpha1_CertificateStoreSpec(in, out, s)
+}
+
+func autoConvert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in *CertificateStoreStatus, out *unversioned.CertificateStoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus is an autogenerated conversion function.
+func Convert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in *CertificateStoreStatus, out *unversioned.CertificateStoreStatus, s conversion.Scope) error {
+	return autoConvert_v1alpha1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus(in *unversioned.CertificateStoreStatus, out *CertificateStoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus(in *unversioned.CertificateStoreStatus, out *CertificateStoreStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreStatus_To_v1alpha1_CertificateStoreStatus(in, out, s)
+}
+
+func autoConvert_v1alpha1_PluginSource_To_unversioned_PluginSource(in *PluginSource, out *unversioned.PluginSource, s conversion.Scope) error {
+	out.Artifact = in.Artifact
+	out.AuthProvider = in.AuthProvider
+	return nil
+}
+
+// Convert_v1alpha1_PluginSource_To_unversioned_PluginSource is an autogenerated conversion function.
+func Convert_v1alpha1_PluginSource_To_unversioned_PluginSource(in *PluginSource, out *unversioned.PluginSource, s conversion.Scope) error {
+	return autoConvert_v1alpha1_PluginSource_To_unversioned_PluginSource(in, out, s)
+}
+
+func autoConvert_unversioned_PluginSource_To_v1alpha1_PluginSource(in *unversioned.PluginSource, out *PluginSource, s conversion.Scope) error {
+	out.Artifact = in.Artifact
+	out.AuthProvider = in.AuthProvider
+	return nil
+}
+
+// Convert_unversioned_PluginSource_To_v1alpha1_PluginSource is an autogenerated conversion function.
+func Convert_unversioned_PluginSource_To_v1alpha1_PluginSource(in *unversioned.PluginSource, out *PluginSource, s conversion.Scope) error {
+	return autoConvert_unversioned_PluginSource_To_v1alpha1_PluginSource(in, out, s)
+}
+
+func autoConvert_v1alpha1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1alpha1_StoreStatus_To_unversioned_StoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1alpha1_Store_To_unversioned_Store is an autogenerated conversion function.
+func Convert_v1alpha1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error {
+	return autoConvert_v1alpha1_Store_To_unversioned_Store(in, out, s)
+}
+
+func autoConvert_unversioned_Store_To_v1alpha1_Store(in *unversioned.Store, out *Store, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_StoreStatus_To_v1alpha1_StoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_Store_To_v1alpha1_Store is an autogenerated conversion function.
+func Convert_unversioned_Store_To_v1alpha1_Store(in *unversioned.Store, out *Store, s conversion.Scope) error {
+	return autoConvert_unversioned_Store_To_v1alpha1_Store(in, out, s)
+}
+
+func autoConvert_v1alpha1_StoreList_To_unversioned_StoreList(in *StoreList, out *unversioned.StoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.Store)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1alpha1_StoreList_To_unversioned_StoreList is an autogenerated conversion function.
+func Convert_v1alpha1_StoreList_To_unversioned_StoreList(in *StoreList, out *unversioned.StoreList, s conversion.Scope) error {
+	return autoConvert_v1alpha1_StoreList_To_unversioned_StoreList(in, out, s)
+}
+
+func autoConvert_unversioned_StoreList_To_v1alpha1_StoreList(in *unversioned.StoreList, out *StoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]Store)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_StoreList_To_v1alpha1_StoreList is an autogenerated conversion function.
+func Convert_unversioned_StoreList_To_v1alpha1_StoreList(in *unversioned.StoreList, out *StoreList, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreList_To_v1alpha1_StoreList(in, out, s)
+}
+
+func autoConvert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(in *StoreSpec, out *unversioned.StoreSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Address = in.Address
+	out.Source = (*unversioned.PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1alpha1_StoreSpec_To_unversioned_StoreSpec is an autogenerated conversion function.
+func Convert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(in *StoreSpec, out *unversioned.StoreSpec, s conversion.Scope) error {
+	return autoConvert_v1alpha1_StoreSpec_To_unversioned_StoreSpec(in, out, s)
+}
+
+func autoConvert_unversioned_StoreSpec_To_v1alpha1_StoreSpec(in *unversioned.StoreSpec, out *StoreSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Address = in.Address
+	out.Source = (*PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec is an autogenerated conversion function.
+func Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec(in *unversioned.StoreSpec, out *StoreSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreSpec_To_v1alpha1_StoreSpec(in, out, s)
+}
+
+func autoConvert_v1alpha1_StoreStatus_To_unversioned_StoreStatus(in *StoreStatus, out *unversioned.StoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1alpha1_StoreStatus_To_unversioned_StoreStatus is an autogenerated conversion function.
+func Convert_v1alpha1_StoreStatus_To_unversioned_StoreStatus(in *StoreStatus, out *unversioned.StoreStatus, s conversion.Scope) error {
+	return autoConvert_v1alpha1_StoreStatus_To_unversioned_StoreStatus(in, out, s)
+}
+
+func autoConvert_unversioned_StoreStatus_To_v1alpha1_StoreStatus(in *unversioned.StoreStatus, out *StoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_StoreStatus_To_v1alpha1_StoreStatus is an autogenerated conversion function.
+func Convert_unversioned_StoreStatus_To_v1alpha1_StoreStatus(in *unversioned.StoreStatus, out *StoreStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreStatus_To_v1alpha1_StoreStatus(in, out, s)
+}
+
+func autoConvert_v1alpha1_Verifier_To_unversioned_Verifier(in *Verifier, out *unversioned.Verifier, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1alpha1_Verifier_To_unversioned_Verifier is an autogenerated conversion function.
+func Convert_v1alpha1_Verifier_To_unversioned_Verifier(in *Verifier, out *unversioned.Verifier, s conversion.Scope) error {
+	return autoConvert_v1alpha1_Verifier_To_unversioned_Verifier(in, out, s)
+}
+
+func autoConvert_unversioned_Verifier_To_v1alpha1_Verifier(in *unversioned.Verifier, out *Verifier, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_Verifier_To_v1alpha1_Verifier is an autogenerated conversion function.
+func Convert_unversioned_Verifier_To_v1alpha1_Verifier(in *unversioned.Verifier, out *Verifier, s conversion.Scope) error {
+	return autoConvert_unversioned_Verifier_To_v1alpha1_Verifier(in, out, s)
+}
+
+func autoConvert_v1alpha1_VerifierList_To_unversioned_VerifierList(in *VerifierList, out *unversioned.VerifierList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.Verifier)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1alpha1_VerifierList_To_unversioned_VerifierList is an autogenerated conversion function.
+func Convert_v1alpha1_VerifierList_To_unversioned_VerifierList(in *VerifierList, out *unversioned.VerifierList, s conversion.Scope) error {
+	return autoConvert_v1alpha1_VerifierList_To_unversioned_VerifierList(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierList_To_v1alpha1_VerifierList(in *unversioned.VerifierList, out *VerifierList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]Verifier)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_VerifierList_To_v1alpha1_VerifierList is an autogenerated conversion function.
+func Convert_unversioned_VerifierList_To_v1alpha1_VerifierList(in *unversioned.VerifierList, out *VerifierList, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierList_To_v1alpha1_VerifierList(in, out, s)
+}
+
+func autoConvert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.ArtifactTypes = in.ArtifactTypes
+	out.Address = in.Address
+	out.Source = (*unversioned.PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec is an autogenerated conversion function.
+func Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
+	return autoConvert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.ArtifactTypes = in.ArtifactTypes
+	out.Address = in.Address
+	out.Source = (*PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec is an autogenerated conversion function.
+func Convert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(in, out, s)
+}
+
+func autoConvert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus(in *VerifierStatus, out *unversioned.VerifierStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus is an autogenerated conversion function.
+func Convert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus(in *VerifierStatus, out *unversioned.VerifierStatus, s conversion.Scope) error {
+	return autoConvert_v1alpha1_VerifierStatus_To_unversioned_VerifierStatus(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus(in *unversioned.VerifierStatus, out *VerifierStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus is an autogenerated conversion function.
+func Convert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus(in *unversioned.VerifierStatus, out *VerifierStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierStatus_To_v1alpha1_VerifierStatus(in, out, s)
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index e51352f..4952bff 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -2,7 +2,7 @@
 // +build !ignore_autogenerated
 
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/api/v1beta1/common.go b/api/v1beta1/common.go
new file mode 100644
index 0000000..c3ec88a
--- /dev/null
+++ b/api/v1beta1/common.go
@@ -0,0 +1,30 @@
+/*
+Copyright The Ratify 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 v1beta1
+
+import runtime "k8s.io/apimachinery/pkg/runtime"
+
+// PluginSource defines the fields needed to download a plugin from an OCI Artifact source
+type PluginSource struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// OCI Artifact source to download the plugin from
+	Artifact string `json:"artifact,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// AuthProvider to use to authenticate to the OCI Artifact source, optional
+	AuthProvider runtime.RawExtension `json:"authProvider,omitempty"`
+}
diff --git a/api/v1beta1/doc.go b/api/v1beta1/doc.go
new file mode 100644
index 0000000..7d2226e
--- /dev/null
+++ b/api/v1beta1/doc.go
@@ -0,0 +1,18 @@
+/*
+Copyright The Ratify 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.
+*/
+
+// +k8s:conversion-gen=github.com/deislabs/ratify/api/unversioned
+package v1beta1
diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go
new file mode 100644
index 0000000..97a2a6d
--- /dev/null
+++ b/api/v1beta1/groupversion_info.go
@@ -0,0 +1,39 @@
+/*
+Copyright The Ratify 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 v1beta1 contains API Schema definitions for the config.ratify.deislabs.io v1beta1 API group
+// +kubebuilder:object:generate=true
+// +groupName=config.ratify.deislabs.io
+package v1beta1
+
+import (
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"sigs.k8s.io/controller-runtime/pkg/scheme"
+)
+
+var (
+	// GroupVersion is group version used to register these objects
+	GroupVersion = schema.GroupVersion{Group: "config.ratify.deislabs.io", Version: "v1beta1"}
+
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
+	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+
+	// AddToScheme adds the types in this group-version to the given scheme.
+	AddToScheme = SchemeBuilder.AddToScheme
+
+	localSchemeBuilder = runtime.NewSchemeBuilder(SchemeBuilder.AddToScheme)
+)
diff --git a/api/v1beta1/store_types.go b/api/v1beta1/store_types.go
new file mode 100644
index 0000000..c9de677
--- /dev/null
+++ b/api/v1beta1/store_types.go
@@ -0,0 +1,68 @@
+/*
+Copyright The Ratify 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 v1beta1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// StoreSpec defines the desired state of Store
+type StoreSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the store
+	Name string `json:"name,omitempty"`
+	// Plugin path, optional
+	Address string `json:"address,omitempty"`
+	// OCI Artifact source to download the plugin from, optional
+	Source *PluginSource `json:"source,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// Parameters of the store
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// StoreStatus defines the observed state of Store
+type StoreStatus struct {
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:storageversion
+// Store is the Schema for the stores API
+type Store struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   StoreSpec   `json:"spec,omitempty"`
+	Status StoreStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:storageversion
+// StoreList contains a list of Store
+type StoreList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Store `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&Store{}, &StoreList{})
+}
diff --git a/api/v1beta1/verifier_types.go b/api/v1beta1/verifier_types.go
new file mode 100644
index 0000000..41668b0
--- /dev/null
+++ b/api/v1beta1/verifier_types.go
@@ -0,0 +1,74 @@
+/*
+Copyright The Ratify 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 v1beta1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// VerifierSpec defines the desired state of Verifier
+type VerifierSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the verifier
+	Name string `json:"name,omitempty"`
+
+	// The type of artifact this verifier handles
+	ArtifactTypes string `json:"artifactTypes,omitempty"`
+
+	// # Optional. URL/file path
+	Address string `json:"address,omitempty"`
+
+	// OCI Artifact source to download the plugin from, optional
+	Source *PluginSource `json:"source,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// Parameters for this verifier
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// VerifierStatus defines the observed state of Verifier
+type VerifierStatus struct {
+	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:storageversion
+// Verifier is the Schema for the verifiers API
+type Verifier struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   VerifierSpec   `json:"spec,omitempty"`
+	Status VerifierStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:storageversion
+// VerifierList contains a list of Verifier
+type VerifierList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Verifier `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&Verifier{}, &VerifierList{})
+}
diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go
new file mode 100644
index 0000000..9d39505
--- /dev/null
+++ b/api/v1beta1/zz_generated.conversion.go
@@ -0,0 +1,483 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright The Ratify 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 conversion-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+	unsafe "unsafe"
+
+	unversioned "github.com/deislabs/ratify/api/unversioned"
+	conversion "k8s.io/apimachinery/pkg/conversion"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+func init() {
+	localSchemeBuilder.Register(RegisterConversions)
+}
+
+// RegisterConversions adds conversion functions to the given scheme.
+// Public to allow building arbitrary schemes.
+func RegisterConversions(s *runtime.Scheme) error {
+	if err := s.AddGeneratedConversionFunc((*CertificateStore)(nil), (*unversioned.CertificateStore)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_CertificateStore_To_unversioned_CertificateStore(a.(*CertificateStore), b.(*unversioned.CertificateStore), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStore)(nil), (*CertificateStore)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStore_To_v1beta1_CertificateStore(a.(*unversioned.CertificateStore), b.(*CertificateStore), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreList)(nil), (*unversioned.CertificateStoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_CertificateStoreList_To_unversioned_CertificateStoreList(a.(*CertificateStoreList), b.(*unversioned.CertificateStoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreList)(nil), (*CertificateStoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreList_To_v1beta1_CertificateStoreList(a.(*unversioned.CertificateStoreList), b.(*CertificateStoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreSpec)(nil), (*unversioned.CertificateStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(a.(*CertificateStoreSpec), b.(*unversioned.CertificateStoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreSpec)(nil), (*CertificateStoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec(a.(*unversioned.CertificateStoreSpec), b.(*CertificateStoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*CertificateStoreStatus)(nil), (*unversioned.CertificateStoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(a.(*CertificateStoreStatus), b.(*unversioned.CertificateStoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.CertificateStoreStatus)(nil), (*CertificateStoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus(a.(*unversioned.CertificateStoreStatus), b.(*CertificateStoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*PluginSource)(nil), (*unversioned.PluginSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_PluginSource_To_unversioned_PluginSource(a.(*PluginSource), b.(*unversioned.PluginSource), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.PluginSource)(nil), (*PluginSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_PluginSource_To_v1beta1_PluginSource(a.(*unversioned.PluginSource), b.(*PluginSource), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*Store)(nil), (*unversioned.Store)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_Store_To_unversioned_Store(a.(*Store), b.(*unversioned.Store), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.Store)(nil), (*Store)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_Store_To_v1beta1_Store(a.(*unversioned.Store), b.(*Store), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreList)(nil), (*unversioned.StoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_StoreList_To_unversioned_StoreList(a.(*StoreList), b.(*unversioned.StoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreList)(nil), (*StoreList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreList_To_v1beta1_StoreList(a.(*unversioned.StoreList), b.(*StoreList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreSpec)(nil), (*unversioned.StoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_StoreSpec_To_unversioned_StoreSpec(a.(*StoreSpec), b.(*unversioned.StoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreSpec)(nil), (*StoreSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreSpec_To_v1beta1_StoreSpec(a.(*unversioned.StoreSpec), b.(*StoreSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*StoreStatus)(nil), (*unversioned.StoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_StoreStatus_To_unversioned_StoreStatus(a.(*StoreStatus), b.(*unversioned.StoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.StoreStatus)(nil), (*StoreStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_StoreStatus_To_v1beta1_StoreStatus(a.(*unversioned.StoreStatus), b.(*StoreStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*Verifier)(nil), (*unversioned.Verifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_Verifier_To_unversioned_Verifier(a.(*Verifier), b.(*unversioned.Verifier), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.Verifier)(nil), (*Verifier)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_Verifier_To_v1beta1_Verifier(a.(*unversioned.Verifier), b.(*Verifier), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierList)(nil), (*unversioned.VerifierList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_VerifierList_To_unversioned_VerifierList(a.(*VerifierList), b.(*unversioned.VerifierList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierList)(nil), (*VerifierList)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierList_To_v1beta1_VerifierList(a.(*unversioned.VerifierList), b.(*VerifierList), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierSpec)(nil), (*unversioned.VerifierSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(a.(*VerifierSpec), b.(*unversioned.VerifierSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierSpec)(nil), (*VerifierSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(a.(*unversioned.VerifierSpec), b.(*VerifierSpec), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*VerifierStatus)(nil), (*unversioned.VerifierStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus(a.(*VerifierStatus), b.(*unversioned.VerifierStatus), scope)
+	}); err != nil {
+		return err
+	}
+	if err := s.AddGeneratedConversionFunc((*unversioned.VerifierStatus)(nil), (*VerifierStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
+		return Convert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus(a.(*unversioned.VerifierStatus), b.(*VerifierStatus), scope)
+	}); err != nil {
+		return err
+	}
+	return nil
+}
+
+func autoConvert_v1beta1_CertificateStore_To_unversioned_CertificateStore(in *CertificateStore, out *unversioned.CertificateStore, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1beta1_CertificateStore_To_unversioned_CertificateStore is an autogenerated conversion function.
+func Convert_v1beta1_CertificateStore_To_unversioned_CertificateStore(in *CertificateStore, out *unversioned.CertificateStore, s conversion.Scope) error {
+	return autoConvert_v1beta1_CertificateStore_To_unversioned_CertificateStore(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStore_To_v1beta1_CertificateStore(in *unversioned.CertificateStore, out *CertificateStore, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_CertificateStore_To_v1beta1_CertificateStore is an autogenerated conversion function.
+func Convert_unversioned_CertificateStore_To_v1beta1_CertificateStore(in *unversioned.CertificateStore, out *CertificateStore, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStore_To_v1beta1_CertificateStore(in, out, s)
+}
+
+func autoConvert_v1beta1_CertificateStoreList_To_unversioned_CertificateStoreList(in *CertificateStoreList, out *unversioned.CertificateStoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.CertificateStore)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1beta1_CertificateStoreList_To_unversioned_CertificateStoreList is an autogenerated conversion function.
+func Convert_v1beta1_CertificateStoreList_To_unversioned_CertificateStoreList(in *CertificateStoreList, out *unversioned.CertificateStoreList, s conversion.Scope) error {
+	return autoConvert_v1beta1_CertificateStoreList_To_unversioned_CertificateStoreList(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreList_To_v1beta1_CertificateStoreList(in *unversioned.CertificateStoreList, out *CertificateStoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]CertificateStore)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreList_To_v1beta1_CertificateStoreList is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreList_To_v1beta1_CertificateStoreList(in *unversioned.CertificateStoreList, out *CertificateStoreList, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreList_To_v1beta1_CertificateStoreList(in, out, s)
+}
+
+func autoConvert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in *CertificateStoreSpec, out *unversioned.CertificateStoreSpec, s conversion.Scope) error {
+	out.Provider = in.Provider
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec is an autogenerated conversion function.
+func Convert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in *CertificateStoreSpec, out *unversioned.CertificateStoreSpec, s conversion.Scope) error {
+	return autoConvert_v1beta1_CertificateStoreSpec_To_unversioned_CertificateStoreSpec(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec(in *unversioned.CertificateStoreSpec, out *CertificateStoreSpec, s conversion.Scope) error {
+	out.Provider = in.Provider
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec(in *unversioned.CertificateStoreSpec, out *CertificateStoreSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreSpec_To_v1beta1_CertificateStoreSpec(in, out, s)
+}
+
+func autoConvert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in *CertificateStoreStatus, out *unversioned.CertificateStoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus is an autogenerated conversion function.
+func Convert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in *CertificateStoreStatus, out *unversioned.CertificateStoreStatus, s conversion.Scope) error {
+	return autoConvert_v1beta1_CertificateStoreStatus_To_unversioned_CertificateStoreStatus(in, out, s)
+}
+
+func autoConvert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus(in *unversioned.CertificateStoreStatus, out *CertificateStoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus is an autogenerated conversion function.
+func Convert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus(in *unversioned.CertificateStoreStatus, out *CertificateStoreStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_CertificateStoreStatus_To_v1beta1_CertificateStoreStatus(in, out, s)
+}
+
+func autoConvert_v1beta1_PluginSource_To_unversioned_PluginSource(in *PluginSource, out *unversioned.PluginSource, s conversion.Scope) error {
+	out.Artifact = in.Artifact
+	out.AuthProvider = in.AuthProvider
+	return nil
+}
+
+// Convert_v1beta1_PluginSource_To_unversioned_PluginSource is an autogenerated conversion function.
+func Convert_v1beta1_PluginSource_To_unversioned_PluginSource(in *PluginSource, out *unversioned.PluginSource, s conversion.Scope) error {
+	return autoConvert_v1beta1_PluginSource_To_unversioned_PluginSource(in, out, s)
+}
+
+func autoConvert_unversioned_PluginSource_To_v1beta1_PluginSource(in *unversioned.PluginSource, out *PluginSource, s conversion.Scope) error {
+	out.Artifact = in.Artifact
+	out.AuthProvider = in.AuthProvider
+	return nil
+}
+
+// Convert_unversioned_PluginSource_To_v1beta1_PluginSource is an autogenerated conversion function.
+func Convert_unversioned_PluginSource_To_v1beta1_PluginSource(in *unversioned.PluginSource, out *PluginSource, s conversion.Scope) error {
+	return autoConvert_unversioned_PluginSource_To_v1beta1_PluginSource(in, out, s)
+}
+
+func autoConvert_v1beta1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1beta1_StoreSpec_To_unversioned_StoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1beta1_StoreStatus_To_unversioned_StoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1beta1_Store_To_unversioned_Store is an autogenerated conversion function.
+func Convert_v1beta1_Store_To_unversioned_Store(in *Store, out *unversioned.Store, s conversion.Scope) error {
+	return autoConvert_v1beta1_Store_To_unversioned_Store(in, out, s)
+}
+
+func autoConvert_unversioned_Store_To_v1beta1_Store(in *unversioned.Store, out *Store, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_StoreSpec_To_v1beta1_StoreSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_StoreStatus_To_v1beta1_StoreStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_Store_To_v1beta1_Store is an autogenerated conversion function.
+func Convert_unversioned_Store_To_v1beta1_Store(in *unversioned.Store, out *Store, s conversion.Scope) error {
+	return autoConvert_unversioned_Store_To_v1beta1_Store(in, out, s)
+}
+
+func autoConvert_v1beta1_StoreList_To_unversioned_StoreList(in *StoreList, out *unversioned.StoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.Store)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1beta1_StoreList_To_unversioned_StoreList is an autogenerated conversion function.
+func Convert_v1beta1_StoreList_To_unversioned_StoreList(in *StoreList, out *unversioned.StoreList, s conversion.Scope) error {
+	return autoConvert_v1beta1_StoreList_To_unversioned_StoreList(in, out, s)
+}
+
+func autoConvert_unversioned_StoreList_To_v1beta1_StoreList(in *unversioned.StoreList, out *StoreList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]Store)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_StoreList_To_v1beta1_StoreList is an autogenerated conversion function.
+func Convert_unversioned_StoreList_To_v1beta1_StoreList(in *unversioned.StoreList, out *StoreList, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreList_To_v1beta1_StoreList(in, out, s)
+}
+
+func autoConvert_v1beta1_StoreSpec_To_unversioned_StoreSpec(in *StoreSpec, out *unversioned.StoreSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Address = in.Address
+	out.Source = (*unversioned.PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1beta1_StoreSpec_To_unversioned_StoreSpec is an autogenerated conversion function.
+func Convert_v1beta1_StoreSpec_To_unversioned_StoreSpec(in *StoreSpec, out *unversioned.StoreSpec, s conversion.Scope) error {
+	return autoConvert_v1beta1_StoreSpec_To_unversioned_StoreSpec(in, out, s)
+}
+
+func autoConvert_unversioned_StoreSpec_To_v1beta1_StoreSpec(in *unversioned.StoreSpec, out *StoreSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.Address = in.Address
+	out.Source = (*PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_StoreSpec_To_v1beta1_StoreSpec is an autogenerated conversion function.
+func Convert_unversioned_StoreSpec_To_v1beta1_StoreSpec(in *unversioned.StoreSpec, out *StoreSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreSpec_To_v1beta1_StoreSpec(in, out, s)
+}
+
+func autoConvert_v1beta1_StoreStatus_To_unversioned_StoreStatus(in *StoreStatus, out *unversioned.StoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1beta1_StoreStatus_To_unversioned_StoreStatus is an autogenerated conversion function.
+func Convert_v1beta1_StoreStatus_To_unversioned_StoreStatus(in *StoreStatus, out *unversioned.StoreStatus, s conversion.Scope) error {
+	return autoConvert_v1beta1_StoreStatus_To_unversioned_StoreStatus(in, out, s)
+}
+
+func autoConvert_unversioned_StoreStatus_To_v1beta1_StoreStatus(in *unversioned.StoreStatus, out *StoreStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_StoreStatus_To_v1beta1_StoreStatus is an autogenerated conversion function.
+func Convert_unversioned_StoreStatus_To_v1beta1_StoreStatus(in *unversioned.StoreStatus, out *StoreStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_StoreStatus_To_v1beta1_StoreStatus(in, out, s)
+}
+
+func autoConvert_v1beta1_Verifier_To_unversioned_Verifier(in *Verifier, out *unversioned.Verifier, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_v1beta1_Verifier_To_unversioned_Verifier is an autogenerated conversion function.
+func Convert_v1beta1_Verifier_To_unversioned_Verifier(in *Verifier, out *unversioned.Verifier, s conversion.Scope) error {
+	return autoConvert_v1beta1_Verifier_To_unversioned_Verifier(in, out, s)
+}
+
+func autoConvert_unversioned_Verifier_To_v1beta1_Verifier(in *unversioned.Verifier, out *Verifier, s conversion.Scope) error {
+	out.ObjectMeta = in.ObjectMeta
+	if err := Convert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(&in.Spec, &out.Spec, s); err != nil {
+		return err
+	}
+	if err := Convert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus(&in.Status, &out.Status, s); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Convert_unversioned_Verifier_To_v1beta1_Verifier is an autogenerated conversion function.
+func Convert_unversioned_Verifier_To_v1beta1_Verifier(in *unversioned.Verifier, out *Verifier, s conversion.Scope) error {
+	return autoConvert_unversioned_Verifier_To_v1beta1_Verifier(in, out, s)
+}
+
+func autoConvert_v1beta1_VerifierList_To_unversioned_VerifierList(in *VerifierList, out *unversioned.VerifierList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]unversioned.Verifier)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_v1beta1_VerifierList_To_unversioned_VerifierList is an autogenerated conversion function.
+func Convert_v1beta1_VerifierList_To_unversioned_VerifierList(in *VerifierList, out *unversioned.VerifierList, s conversion.Scope) error {
+	return autoConvert_v1beta1_VerifierList_To_unversioned_VerifierList(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierList_To_v1beta1_VerifierList(in *unversioned.VerifierList, out *VerifierList, s conversion.Scope) error {
+	out.ListMeta = in.ListMeta
+	out.Items = *(*[]Verifier)(unsafe.Pointer(&in.Items))
+	return nil
+}
+
+// Convert_unversioned_VerifierList_To_v1beta1_VerifierList is an autogenerated conversion function.
+func Convert_unversioned_VerifierList_To_v1beta1_VerifierList(in *unversioned.VerifierList, out *VerifierList, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierList_To_v1beta1_VerifierList(in, out, s)
+}
+
+func autoConvert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.ArtifactTypes = in.ArtifactTypes
+	out.Address = in.Address
+	out.Source = (*unversioned.PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec is an autogenerated conversion function.
+func Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
+	return autoConvert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
+	out.Name = in.Name
+	out.ArtifactTypes = in.ArtifactTypes
+	out.Address = in.Address
+	out.Source = (*PluginSource)(unsafe.Pointer(in.Source))
+	out.Parameters = in.Parameters
+	return nil
+}
+
+// Convert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec is an autogenerated conversion function.
+func Convert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(in, out, s)
+}
+
+func autoConvert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus(in *VerifierStatus, out *unversioned.VerifierStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus is an autogenerated conversion function.
+func Convert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus(in *VerifierStatus, out *unversioned.VerifierStatus, s conversion.Scope) error {
+	return autoConvert_v1beta1_VerifierStatus_To_unversioned_VerifierStatus(in, out, s)
+}
+
+func autoConvert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus(in *unversioned.VerifierStatus, out *VerifierStatus, s conversion.Scope) error {
+	return nil
+}
+
+// Convert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus is an autogenerated conversion function.
+func Convert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus(in *unversioned.VerifierStatus, out *VerifierStatus, s conversion.Scope) error {
+	return autoConvert_unversioned_VerifierStatus_To_v1beta1_VerifierStatus(in, out, s)
+}
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
new file mode 100644
index 0000000..a4e876e
--- /dev/null
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -0,0 +1,322 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright The Ratify 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 controller-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStore) DeepCopyInto(out *CertificateStore) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStore.
+func (in *CertificateStore) DeepCopy() *CertificateStore {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStore)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CertificateStore) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreList) DeepCopyInto(out *CertificateStoreList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]CertificateStore, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreList.
+func (in *CertificateStoreList) DeepCopy() *CertificateStoreList {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CertificateStoreList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreSpec) DeepCopyInto(out *CertificateStoreSpec) {
+	*out = *in
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreSpec.
+func (in *CertificateStoreSpec) DeepCopy() *CertificateStoreSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertificateStoreStatus) DeepCopyInto(out *CertificateStoreStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateStoreStatus.
+func (in *CertificateStoreStatus) DeepCopy() *CertificateStoreStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(CertificateStoreStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PluginSource) DeepCopyInto(out *PluginSource) {
+	*out = *in
+	in.AuthProvider.DeepCopyInto(&out.AuthProvider)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginSource.
+func (in *PluginSource) DeepCopy() *PluginSource {
+	if in == nil {
+		return nil
+	}
+	out := new(PluginSource)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Store) DeepCopyInto(out *Store) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Store.
+func (in *Store) DeepCopy() *Store {
+	if in == nil {
+		return nil
+	}
+	out := new(Store)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Store) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreList) DeepCopyInto(out *StoreList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Store, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreList.
+func (in *StoreList) DeepCopy() *StoreList {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *StoreList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreSpec) DeepCopyInto(out *StoreSpec) {
+	*out = *in
+	if in.Source != nil {
+		in, out := &in.Source, &out.Source
+		*out = new(PluginSource)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreSpec.
+func (in *StoreSpec) DeepCopy() *StoreSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreStatus) DeepCopyInto(out *StoreStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreStatus.
+func (in *StoreStatus) DeepCopy() *StoreStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Verifier) DeepCopyInto(out *Verifier) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Verifier.
+func (in *Verifier) DeepCopy() *Verifier {
+	if in == nil {
+		return nil
+	}
+	out := new(Verifier)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Verifier) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierList) DeepCopyInto(out *VerifierList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Verifier, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierList.
+func (in *VerifierList) DeepCopy() *VerifierList {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *VerifierList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierSpec) DeepCopyInto(out *VerifierSpec) {
+	*out = *in
+	if in.Source != nil {
+		in, out := &in.Source, &out.Source
+		*out = new(PluginSource)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierSpec.
+func (in *VerifierSpec) DeepCopy() *VerifierSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierStatus) DeepCopyInto(out *VerifierStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierStatus.
+func (in *VerifierStatus) DeepCopy() *VerifierStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierStatus)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/charts/ratify/crds/store-customresourcedefinition.yaml b/charts/ratify/crds/store-customresourcedefinition.yaml
index b46587f..cfef6bb 100644
--- a/charts/ratify/crds/store-customresourcedefinition.yaml
+++ b/charts/ratify/crds/store-customresourcedefinition.yaml
@@ -3,6 +3,7 @@ kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.9.2
+  creationTimestamp: null
   name: stores.config.ratify.deislabs.io
 spec:
   group: config.ratify.deislabs.io
@@ -13,16 +14,23 @@ spec:
     singular: store
   scope: Cluster
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the eraser API has been deprecated. Please migrate
+      to v1beta1.
+    name: v1alpha1
     schema:
       openAPIV3Schema:
         description: Store is the Schema for the stores API
         properties:
           apiVersion:
-            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
             type: string
           kind:
-            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
             type: string
           metadata:
             type: object
@@ -33,10 +41,59 @@ spec:
                 description: Plugin path, optional
                 type: string
               name:
-                description: Name of the verifier
+                description: Name of the store
                 type: string
               parameters:
-                description: Parameters of this store
+                description: Parameters of the store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              source:
+                description: OCI Artifact source to download the plugin from, optional
+                properties:
+                  artifact:
+                    description: OCI Artifact source to download the plugin from
+                    type: string
+                  authProvider:
+                    description: AuthProvider to use to authenticate to the OCI Artifact
+                      source, optional
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                type: object
+            type: object
+          status:
+            description: StoreStatus defines the observed state of Store
+            type: object
+        type: object
+    served: true
+    storage: false
+  - name: v1beta1
+    schema:
+      openAPIV3Schema:
+        description: Store is the Schema for the stores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: StoreSpec defines the desired state of Store
+            properties:
+              address:
+                description: Plugin path, optional
+                type: string
+              name:
+                description: Name of the store
+                type: string
+              parameters:
+                description: Parameters of the store
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
diff --git a/charts/ratify/crds/verifier-customresourcedefinition.yaml b/charts/ratify/crds/verifier-customresourcedefinition.yaml
index a4ba279..f5da1f4 100644
--- a/charts/ratify/crds/verifier-customresourcedefinition.yaml
+++ b/charts/ratify/crds/verifier-customresourcedefinition.yaml
@@ -3,6 +3,7 @@ kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.9.2
+  creationTimestamp: null
   name: verifiers.config.ratify.deislabs.io
 spec:
   group: config.ratify.deislabs.io
@@ -13,16 +14,23 @@ spec:
     singular: verifier
   scope: Cluster
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the eraser API has been deprecated. Please migrate
+      to v1beta1.
+    name: v1alpha1
     schema:
       openAPIV3Schema:
         description: Verifier is the Schema for the verifiers API
         properties:
           apiVersion:
-            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
             type: string
           kind:
-            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
             type: string
           metadata:
             type: object
@@ -39,7 +47,59 @@ spec:
                 description: Name of the verifier
                 type: string
               parameters:
-                description: Parameters of this verifier
+                description: Parameters for this verifier
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              source:
+                description: OCI Artifact source to download the plugin from, optional
+                properties:
+                  artifact:
+                    description: OCI Artifact source to download the plugin from
+                    type: string
+                  authProvider:
+                    description: AuthProvider to use to authenticate to the OCI Artifact
+                      source, optional
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                type: object
+            type: object
+          status:
+            description: VerifierStatus defines the observed state of Verifier
+            type: object
+        type: object
+    served: true
+    storage: false
+  - name: v1beta1
+    schema:
+      openAPIV3Schema:
+        description: Verifier is the Schema for the verifiers API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: VerifierSpec defines the desired state of Verifier
+            properties:
+              address:
+                description: '# Optional. URL/file path'
+                type: string
+              artifactTypes:
+                description: The type of artifact this verifier handles
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters for this verifier
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
diff --git a/charts/ratify/templates/akv-certificate-provider.yaml b/charts/ratify/templates/akv-certificate-provider.yaml
index 9368516..08d5410 100644
--- a/charts/ratify/templates/akv-certificate-provider.yaml
+++ b/charts/ratify/templates/akv-certificate-provider.yaml
@@ -1,5 +1,5 @@
 {{- if .Values.akvCertConfig.enabled }}
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: CertificateStore
 metadata:
   name: certstore-akv
diff --git a/charts/ratify/templates/inline-certificate-provider.yaml b/charts/ratify/templates/inline-certificate-provider.yaml
index 29fb304..b4368bf 100644
--- a/charts/ratify/templates/inline-certificate-provider.yaml
+++ b/charts/ratify/templates/inline-certificate-provider.yaml
@@ -1,5 +1,5 @@
 {{- if eq .Values.akvCertConfig.enabled false }}  
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: CertificateStore
 metadata:
   name: {{ include "ratify.fullname" . }}-notary-inline-cert
diff --git a/charts/ratify/templates/store.yaml b/charts/ratify/templates/store.yaml
index f304933..6d50a97 100644
--- a/charts/ratify/templates/store.yaml
+++ b/charts/ratify/templates/store.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Store
 metadata:
   name: store-oras
diff --git a/charts/ratify/templates/verifier.yaml b/charts/ratify/templates/verifier.yaml
index 52011dd..ec276c7 100644
--- a/charts/ratify/templates/verifier.yaml
+++ b/charts/ratify/templates/verifier.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-notary
@@ -28,7 +28,7 @@ spec:
             - "*"
 ---
 {{- if .Values.cosign.enabled }}
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-cosign
diff --git a/config/crd/bases/config.ratify.deislabs.io_stores.yaml b/config/crd/bases/config.ratify.deislabs.io_stores.yaml
index 531a362..d64f710 100644
--- a/config/crd/bases/config.ratify.deislabs.io_stores.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_stores.yaml
@@ -15,7 +15,59 @@ spec:
     singular: store
   scope: Cluster
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the Store API has been deprecated. Please migrate
+      to v1beta1.
+    name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Store is the Schema for the stores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: StoreSpec defines the desired state of Store
+            properties:
+              address:
+                description: Plugin path, optional
+                type: string
+              name:
+                description: Name of the store
+                type: string
+              parameters:
+                description: Parameters of the store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              source:
+                description: OCI Artifact source to download the plugin from, optional
+                properties:
+                  artifact:
+                    description: OCI Artifact source to download the plugin from
+                    type: string
+                  authProvider:
+                    description: AuthProvider to use to authenticate to the OCI Artifact
+                      source, optional
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                type: object
+            type: object
+          status:
+            description: StoreStatus defines the observed state of Store
+            type: object
+        type: object
+    served: true
+    storage: false
+  - name: v1beta1
     schema:
       openAPIV3Schema:
         description: Store is the Schema for the stores API
diff --git a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
index 6ed3ffc..6d10254 100644
--- a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
@@ -15,7 +15,62 @@ spec:
     singular: verifier
   scope: Cluster
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the Verifier API has been deprecated. Please migrate
+      to v1beta1.
+    name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Verifier is the Schema for the verifiers API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: VerifierSpec defines the desired state of Verifier
+            properties:
+              address:
+                description: '# Optional. URL/file path'
+                type: string
+              artifactTypes:
+                description: The type of artifact this verifier handles
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters for this verifier
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              source:
+                description: OCI Artifact source to download the plugin from, optional
+                properties:
+                  artifact:
+                    description: OCI Artifact source to download the plugin from
+                    type: string
+                  authProvider:
+                    description: AuthProvider to use to authenticate to the OCI Artifact
+                      source, optional
+                    type: object
+                    x-kubernetes-preserve-unknown-fields: true
+                type: object
+            type: object
+          status:
+            description: VerifierStatus defines the observed state of Verifier
+            type: object
+        type: object
+    served: true
+    storage: false
+  - name: v1beta1
     schema:
       openAPIV3Schema:
         description: Verifier is the Schema for the verifiers API
diff --git a/config/samples/config_v1alpha1_store_oras_http.yaml b/config/samples/config_v1alpha1_store_oras_http.yaml
index aae99f1..34854b4 100644
--- a/config/samples/config_v1alpha1_store_oras_http.yaml
+++ b/config/samples/config_v1alpha1_store_oras_http.yaml
@@ -10,4 +10,4 @@ spec:
     cosignEnabled: true
     keyNumber: 10000
     ttl: 10
-    useHttp: true
\ No newline at end of file
+    useHttp: true
diff --git a/config/samples/config_v1alpha1_certstore_akv.yaml b/config/samples/config_v1beta1_certstore_akv.yaml
similarity index 88%
rename from config/samples/config_v1alpha1_certstore_akv.yaml
rename to config/samples/config_v1beta1_certstore_akv.yaml
index f4f6ef7..d6e2354 100644
--- a/config/samples/config_v1alpha1_certstore_akv.yaml
+++ b/config/samples/config_v1beta1_certstore_akv.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: CertificateStore
 metadata:
   name: certstore-akv
diff --git a/config/samples/config_v1alpha1_certstore_inline.yaml b/config/samples/config_v1beta1_certstore_inline.yaml
similarity index 96%
rename from config/samples/config_v1alpha1_certstore_inline.yaml
rename to config/samples/config_v1beta1_certstore_inline.yaml
index 651859a..1715664 100644
--- a/config/samples/config_v1alpha1_certstore_inline.yaml
+++ b/config/samples/config_v1beta1_certstore_inline.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: CertificateStore
 metadata:
   name: certstore-inline
diff --git a/config/samples/config_v1alpha1_store_oras.yaml b/config/samples/config_v1beta1_store_oras.yaml
similarity index 78%
rename from config/samples/config_v1alpha1_store_oras.yaml
rename to config/samples/config_v1beta1_store_oras.yaml
index d34067e..39ce063 100644
--- a/config/samples/config_v1alpha1_store_oras.yaml
+++ b/config/samples/config_v1beta1_store_oras.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Store
 metadata:
   name: store-oras
diff --git a/config/samples/config_v1beta1_store_oras_http.yaml b/config/samples/config_v1beta1_store_oras_http.yaml
new file mode 100644
index 0000000..fb39302
--- /dev/null
+++ b/config/samples/config_v1beta1_store_oras_http.yaml
@@ -0,0 +1,13 @@
+apiVersion: config.ratify.deislabs.io/v1beta1
+kind: Store
+metadata:
+  name: store-oras
+spec:
+  name: oras
+  parameters:
+    cacheEnabled: true
+    capacity: 100
+    cosignEnabled: true
+    keyNumber: 10000
+    ttl: 10
+    useHttp: true
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_store_oras_k8secretAuth.yaml b/config/samples/config_v1beta1_store_oras_k8secretAuth.yaml
similarity index 72%
rename from config/samples/config_v1alpha1_store_oras_k8secretAuth.yaml
rename to config/samples/config_v1beta1_store_oras_k8secretAuth.yaml
index f861c4b..a8b04bf 100644
--- a/config/samples/config_v1alpha1_store_oras_k8secretAuth.yaml
+++ b/config/samples/config_v1beta1_store_oras_k8secretAuth.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Store
 metadata:
   name: store-oras
diff --git a/config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml b/config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
similarity index 86%
rename from config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
rename to config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
index 430e59c..11f6ade 100644
--- a/config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+++ b/config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-license-checker
diff --git a/config/samples/config_v1alpha1_verifier_cosign.yaml b/config/samples/config_v1beta1_verifier_cosign.yaml
similarity index 60%
rename from config/samples/config_v1alpha1_verifier_cosign.yaml
rename to config/samples/config_v1beta1_verifier_cosign.yaml
index cf53a78..70cb12a 100644
--- a/config/samples/config_v1alpha1_verifier_cosign.yaml
+++ b/config/samples/config_v1beta1_verifier_cosign.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-cosign
diff --git a/config/samples/config_v1alpha1_verifier_dynamic.yaml b/config/samples/config_v1beta1_verifier_dynamic.yaml
similarity index 81%
rename from config/samples/config_v1alpha1_verifier_dynamic.yaml
rename to config/samples/config_v1beta1_verifier_dynamic.yaml
index 06d54cc..4b61537 100644
--- a/config/samples/config_v1alpha1_verifier_dynamic.yaml
+++ b/config/samples/config_v1beta1_verifier_dynamic.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-dynamic
diff --git a/config/samples/config_v1beta1_verifier_notary.yaml b/config/samples/config_v1beta1_verifier_notary.yaml
new file mode 100644
index 0000000..822c3ef
--- /dev/null
+++ b/config/samples/config_v1beta1_verifier_notary.yaml
@@ -0,0 +1,23 @@
+apiVersion: config.ratify.deislabs.io/v1beta1
+kind: Verifier
+metadata:
+  name: verifier-notary
+spec:
+  name: notaryv2
+  artifactTypes: application/vnd.cncf.notary.signature
+  parameters:
+     verificationCertStores:
+       certs:
+         - ratify-notary-inline-cert
+     trustPolicyDoc:
+      version: "1.0"
+      trustPolicies:
+        - name: default
+          registryScopes:
+            - "*"
+          signatureVerification:
+            level: strict
+          trustStores:
+            - ca:certs
+          trustedIdentities:
+            - "*"
diff --git a/config/samples/config_v1alpha1_verifier_notary_certstore.yaml b/config/samples/config_v1beta1_verifier_notary_certstore.yaml
similarity index 92%
rename from config/samples/config_v1alpha1_verifier_notary_certstore.yaml
rename to config/samples/config_v1beta1_verifier_notary_certstore.yaml
index 37a29c1..7ee12c0 100644
--- a/config/samples/config_v1alpha1_verifier_notary_certstore.yaml
+++ b/config/samples/config_v1beta1_verifier_notary_certstore.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-notary
diff --git a/config/samples/config_v1alpha1_verifier_partial_licensechecker.yaml b/config/samples/config_v1beta1_verifier_partial_licensechecker.yaml
similarity index 79%
rename from config/samples/config_v1alpha1_verifier_partial_licensechecker.yaml
rename to config/samples/config_v1beta1_verifier_partial_licensechecker.yaml
index 8c25f65..48617c2 100644
--- a/config/samples/config_v1alpha1_verifier_partial_licensechecker.yaml
+++ b/config/samples/config_v1beta1_verifier_partial_licensechecker.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-license-checker
diff --git a/config/samples/config_v1alpha1_verifier_sbom.yaml b/config/samples/config_v1beta1_verifier_sbom.yaml
similarity index 52%
rename from config/samples/config_v1alpha1_verifier_sbom.yaml
rename to config/samples/config_v1beta1_verifier_sbom.yaml
index ca4ac92..db09be5 100644
--- a/config/samples/config_v1alpha1_verifier_sbom.yaml
+++ b/config/samples/config_v1beta1_verifier_sbom.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-sbom
diff --git a/config/samples/config_v1alpha1_verifier_schemavalidator.yaml b/config/samples/config_v1beta1_verifier_schemavalidator.yaml
similarity index 84%
rename from config/samples/config_v1alpha1_verifier_schemavalidator.yaml
rename to config/samples/config_v1beta1_verifier_schemavalidator.yaml
index e9c38c9..5be0cf5 100644
--- a/config/samples/config_v1alpha1_verifier_schemavalidator.yaml
+++ b/config/samples/config_v1beta1_verifier_schemavalidator.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-schemavalidator
diff --git a/config/samples/config_v1alpha1_verifier_schemavalidator_bad.yaml b/config/samples/config_v1beta1_verifier_schemavalidator_bad.yaml
similarity index 84%
rename from config/samples/config_v1alpha1_verifier_schemavalidator_bad.yaml
rename to config/samples/config_v1beta1_verifier_schemavalidator_bad.yaml
index 208799d..a3d39ff 100644
--- a/config/samples/config_v1alpha1_verifier_schemavalidator_bad.yaml
+++ b/config/samples/config_v1beta1_verifier_schemavalidator_bad.yaml
@@ -1,4 +1,4 @@
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-schemavalidator
diff --git a/docs/developer/verifier.md b/docs/developer/verifier.md
index f972fb3..e8014b5 100644
--- a/docs/developer/verifier.md
+++ b/docs/developer/verifier.md
@@ -274,7 +274,7 @@ verificationCertStores property defines a collection of cert store objects. [Tru
 
 A sample notary verifier with verificationCertStores defined:
 ```json=
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-notary
diff --git a/docs/reference/crds/api-upgrade-instruction.md b/docs/reference/crds/api-upgrade-instruction.md
new file mode 100644
index 0000000..fbae651
--- /dev/null
+++ b/docs/reference/crds/api-upgrade-instruction.md
@@ -0,0 +1,110 @@
+It's normal and inevitable to move CRD APIs to newer versions as the project 
+moves to a more stable stage. This doc lists the steps for the first version 
+bump-up from `v1alpha1` to `v1beta1`, which can be referenced when we need to have 
+new API versions in the future.
+
+## Upgrade steps from `v1alpha1` to `v1beta1`
+1.  Controller-runtime models conversion between versions in terms of a 
+"hub and spoke" model. In Ratify, we mark the `unversioned` as the hub version, 
+other versions(`v1alpha1` and `v1beta1`) as spoke versions. New versions would 
+be added as spoke versions.
+
+2. Create new API version by `kubebuilder` command:
+```bash
+kubebuilder create api --group config.ratify.deislabs.io --version v1beta1 --kind <kind>
+```
+kind could be `Store`, `Verifier` and `CertificateStore` respectively.
+
+3. Copy over existing types from `v1alpha1` to `v1beta1`.
+
+4. Create an `unversioned` API by manually copying the existing types from `v1alpha1` to 
+`unversioned` as `kubebuilder` doesn't support `unversioned` as version value.
+
+5. In each spoke version package, add marker `+k8s:conversion-gen` directive 
+pointing to the hub(`unversioned`) version, which must be in `doc.go`. Example:
+```go
+// +k8s:conversion-gen=github.com/deislabs/ratify/api/unversioned
+package v1alpha1
+```
+
+6. In hub(`unversioned`) version package, create `doc.go` and add marker `+kubebuilder:object:generate=true` so that the object generator can use it. Example:
+```go
+package unversioned
+// +kubebuilder:object:generate=true
+```
+
+7. In spoke version packages, add a `localSchemeBuilder = runtime.NewSchemeBuilder(SchemeBuilder.AddToScheme)` in `groupversion_info.go` so the auto-generated code 
+could compile.
+
+8. In hub(`unversioned`) version package, add marker `+kubebuilder:skip` to each 
+API and remove all other markers so that skip kubebuilder processing it.
+
+9. Mark `v1beta1` as the storage version by adding marker `+kubebuilder:storageversion` 
+to the root types. Example:
+```go
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:storageversion
+// Store is the Schema for the stores API
+type Store struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   StoreSpec   `json:"spec,omitempty"`
+	Status StoreStatus `json:"status,omitempty"`
+}
+```
+
+10. In the outdated spoke version package, add marker `+kubebuilder:deprecatedversion:warning=<msg>` to the root type of each API. Example:
+```go
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+// +kubebuilder:deprecatedversion:warning="v1alpha1 of the Store API has been deprecated. Please migrate to v1beta1."
+// Store is the Schema for the stores API
+type Store struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+	Spec   StoreSpec   `json:"spec,omitempty"`
+	Status StoreStatus `json:"status,omitempty"`
+}
+```
+
+11. Run `make manifests generate` to generate CRD objects, DeepCopy methods and conversion methods. `zz_generated.conversion.go` and `zz_generated.deepcopy.go` 
+would be generated in each spoke version package.
+
+## Additional steps while incompatibilities introduced
+
+There is no real change between `v1alpha1` and `v1beta1`, which makes it easier 
+than making incompatible upgrade. If there is an incompatible change introduced 
+in a new version, we could follow the above 11 steps first and then follow the 
+below instruction. Let's take the example of adding a new `Test` field to `StoreSpec`.
+
+1. Add a string field `Test` to `StoreSpec` in both `unversioned` and new version(`v1beta1`) packages.
+
+2. After executing `make manifests generate`, we would get errors similar to:
+```
+E0308 02:20:37.752749 4053005 conversion.go:756] Warning: could not find nor generate a final Conversion function for github.com/deislabs/ratify/api/unversioned.StoreSpec -> github.com/binbin-li/ratify/api/v1alpha1.StoreSpec
+E0308 02:20:37.752867 4053005 conversion.go:757]   the following fields need manual conversion:
+E0308 02:20:37.752874 4053005 conversion.go:759]       - Test
+```
+It means that we need to manually implement the conversion method from `unversioned` 
+to `v1alpha1`.
+
+3. Check the generated `zz_generated.conversion.go` in `v1alpha1` package, we 
+could see errors indicating that `Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec()` 
+was not declared. Now we could create a new file `store_conversion.go` in `v1alpha1` 
+package, and implement this method manually there to resolve the error.
+
+## Upgrade existing objects to a new stored version
+It's safe to use both the old and new versions after upgraded. But if we really 
+want to migrate stored objects to the new version, please follow the instruction:
+[Upgrade existing objects to a new stored version](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#upgrade-existing-objects-to-a-new-stored-version)
+
+## References
+[Kubebuilder tutorial on multi-version API](https://book.kubebuilder.io/multiversion-tutorial/api-changes.html)
+
+[Guide for API conversions](https://cluster-api-ibmcloud.sigs.k8s.io/developer/conversion.html)
+
+[Approach to using conversion-gen with multi-versioning](https://github.com/kubernetes-sigs/kubebuilder/issues/1529#issuecomment-656359330)
+
+[Example PR following same steps](https://github.com/Azure/eraser/pull/544)
\ No newline at end of file
diff --git a/docs/reference/crds/verifiers.md b/docs/reference/crds/verifiers.md
index 74d4ec9..0681008 100644
--- a/docs/reference/crds/verifiers.md
+++ b/docs/reference/crds/verifiers.md
@@ -14,7 +14,7 @@ parameters: optional. Parameters specific to this verifier
 
 Sample Notary yaml spec:
 ```yml
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-notary
diff --git a/docs/reference/dynamic-plugins.md b/docs/reference/dynamic-plugins.md
index 5d9b3b2..0592328 100644
--- a/docs/reference/dynamic-plugins.md
+++ b/docs/reference/dynamic-plugins.md
@@ -40,7 +40,7 @@ helm upgrade ratify \
 The last step is to specify the optional `source` property to tell Ratify where to download the plugin from. Dynamic plugins use the same [auth providers](/docs/reference/oras-auth-provider.md) and options as the builtin ORAS store (ex: `azureWorkloadIdentity`, `awsEcrBasic`, `k8Secrets`) for authentication to the registry where your plugins are located.
 
 ```yaml
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-sample
diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt
index 29c55ec..317daed 100644
--- a/hack/boilerplate.go.txt
+++ b/hack/boilerplate.go.txt
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/pkg/controllers/store_controller.go b/pkg/controllers/store_controller.go
index 4f6dcf6..a12b89a 100644
--- a/pkg/controllers/store_controller.go
+++ b/pkg/controllers/store_controller.go
@@ -25,7 +25,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"github.com/deislabs/ratify/config"
 	"github.com/deislabs/ratify/pkg/referrerstore"
 	rc "github.com/deislabs/ratify/pkg/referrerstore/config"
@@ -57,7 +57,7 @@ var (
 func (r *StoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	storeLogger := logrus.WithContext(ctx)
 
-	var store configv1alpha1.Store
+	var store configv1beta1.Store
 	var resource = req.Name
 	storeLogger.Infof("reconciling store '%v'", resource)
 
@@ -84,12 +84,12 @@ func (r *StoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
 // SetupWithManager sets up the controller with the Manager.
 func (r *StoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
-		For(&configv1alpha1.Store{}).
+		For(&configv1beta1.Store{}).
 		Complete(r)
 }
 
 // Creates a store reference from CRD spec and add store to map
-func storeAddOrReplace(spec configv1alpha1.StoreSpec, fullname string) error {
+func storeAddOrReplace(spec configv1beta1.StoreSpec, fullname string) error {
 	storeConfig, err := specToStoreConfig(spec)
 	if err != nil {
 		return fmt.Errorf("unable to convert store spec to store config, err: %w", err)
@@ -120,7 +120,7 @@ func storeRemove(resourceName string) {
 }
 
 // Returns a store reference from spec
-func specToStoreConfig(storeSpec configv1alpha1.StoreSpec) (rc.StorePluginConfig, error) {
+func specToStoreConfig(storeSpec configv1beta1.StoreSpec) (rc.StorePluginConfig, error) {
 	storeConfig := rc.StorePluginConfig{}
 
 	if string(storeSpec.Parameters.Raw) != "" {
diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go
index 9e9149a..a1d6797 100644
--- a/pkg/controllers/verifier_controller.go
+++ b/pkg/controllers/verifier_controller.go
@@ -20,7 +20,7 @@ import (
 	"encoding/json"
 	"fmt"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"github.com/deislabs/ratify/config"
 	vr "github.com/deislabs/ratify/pkg/verifier"
 	vc "github.com/deislabs/ratify/pkg/verifier/config"
@@ -60,7 +60,7 @@ var (
 func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	verifierLogger := logrus.WithContext(ctx)
 
-	var verifier configv1alpha1.Verifier
+	var verifier configv1beta1.Verifier
 	var resource = req.Name
 	verifierLogger.Infof("reconciling verifier '%v'", resource)
 
@@ -85,7 +85,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 }
 
 // creates a verifier reference from CRD spec and add store to map
-func verifierAddOrReplace(spec configv1alpha1.VerifierSpec, objectName string) error {
+func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string) error {
 	verifierConfig, err := specToVerifierConfig(spec)
 
 	if err != nil {
@@ -118,7 +118,7 @@ func verifierRemove(objectName string) {
 }
 
 // returns a verifier reference from spec
-func specToVerifierConfig(verifierSpec configv1alpha1.VerifierSpec) (vc.VerifierConfig, error) {
+func specToVerifierConfig(verifierSpec configv1beta1.VerifierSpec) (vc.VerifierConfig, error) {
 	verifierConfig := vc.VerifierConfig{}
 
 	if string(verifierSpec.Parameters.Raw) != "" {
@@ -140,6 +140,6 @@ func specToVerifierConfig(verifierSpec configv1alpha1.VerifierSpec) (vc.Verifier
 // SetupWithManager sets up the controller with the Manager.
 func (r *VerifierReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
-		For(&configv1alpha1.Verifier{}).
+		For(&configv1beta1.Verifier{}).
 		Complete(r)
 }
diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go
index 5bc32eb..5a1f5fe 100644
--- a/pkg/manager/manager.go
+++ b/pkg/manager/manager.go
@@ -44,6 +44,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/healthz"
 
 	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"github.com/deislabs/ratify/pkg/controllers"
 	ef "github.com/deislabs/ratify/pkg/executor/core"
 	"github.com/deislabs/ratify/pkg/referrerstore"
@@ -60,6 +61,8 @@ func init() {
 	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
 	utilruntime.Must(configv1alpha1.AddToScheme(scheme))
 	//+kubebuilder:scaffold:scheme
+	utilruntime.Must(configv1beta1.AddToScheme(scheme))
+	//+kubebuilder:scaffold:scheme
 }
 
 func StartServer(httpServerAddress, configFilePath, certDirectory, caCertFile string, cacheSize int, cacheTTL time.Duration) {
diff --git a/plugins/verifier/schemavalidator/README.md b/plugins/verifier/schemavalidator/README.md
index 60aa9e1..215e9d2 100644
--- a/plugins/verifier/schemavalidator/README.md
+++ b/plugins/verifier/schemavalidator/README.md
@@ -17,7 +17,7 @@ Schemas can be configured in Ratify config.json or via CRD.
 ```
 
 ```yaml
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-schemavalidator


Test patch:
diff --git a/api/unversioned/certificatestore_types.go b/api/unversioned/certificatestore_types.go
new file mode 100644
index 0000000..ef0f1d4
--- /dev/null
+++ b/api/unversioned/certificatestore_types.go
@@ -0,0 +1,57 @@
+/*
+Copyright The Ratify 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.
+*/
+
+// +kubebuilder:skip
+package unversioned
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
+
+// CertificateStoreSpec defines the desired state of CertificateStore
+type CertificateStoreSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the certificate store provider
+	Provider string `json:"provider,omitempty"`
+
+	// Parameters of the certificate store
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// CertificateStoreStatus defines the observed state of CertificateStore
+type CertificateStoreStatus struct {
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// CertificateStore is the Schema for the certificatestores API
+type CertificateStore struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   CertificateStoreSpec   `json:"spec,omitempty"`
+	Status CertificateStoreStatus `json:"status,omitempty"`
+}
+
+// CertificateStoreList contains a list of CertificateStore
+type CertificateStoreList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []CertificateStore `json:"items"`
+}
diff --git a/api/v1alpha1/certificatestore_types.go b/api/v1alpha1/certificatestore_types.go
index 6876187..ba24eb8 100644
--- a/api/v1alpha1/certificatestore_types.go
+++ b/api/v1alpha1/certificatestore_types.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2022.
+Copyright The Ratify Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -40,8 +40,9 @@ type CertificateStoreStatus struct {
 	// Important: Run "make" to regenerate code after modifying this file
 }
 
-//+kubebuilder:object:root=true
-//+kubebuilder:subresource:status
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:deprecatedversion:warning="v1alpha1 of the CertificateStore API has been deprecated. Please migrate to v1beta1."
 
 // CertificateStore is the Schema for the certificatestores API
 type CertificateStore struct {
diff --git a/api/v1beta1/certificatestore_types.go b/api/v1beta1/certificatestore_types.go
new file mode 100644
index 0000000..65ef960
--- /dev/null
+++ b/api/v1beta1/certificatestore_types.go
@@ -0,0 +1,66 @@
+/*
+Copyright The Ratify 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 v1beta1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
+
+// CertificateStoreSpec defines the desired state of CertificateStore
+type CertificateStoreSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the certificate store provider
+	Provider string `json:"provider,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// Parameters of the certificate store
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// CertificateStoreStatus defines the observed state of CertificateStore
+type CertificateStoreStatus struct {
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:storageversion
+// CertificateStore is the Schema for the certificatestores API
+type CertificateStore struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   CertificateStoreSpec   `json:"spec,omitempty"`
+	Status CertificateStoreStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:storageversion
+// CertificateStoreList contains a list of CertificateStore
+type CertificateStoreList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []CertificateStore `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&CertificateStore{}, &CertificateStoreList{})
+}
diff --git a/charts/ratify/crds/certificatestore-customresourcedefinition.yaml b/charts/ratify/crds/certificatestore-customresourcedefinition.yaml
index c6963fd..ce3ddcc 100644
--- a/charts/ratify/crds/certificatestore-customresourcedefinition.yaml
+++ b/charts/ratify/crds/certificatestore-customresourcedefinition.yaml
@@ -14,7 +14,10 @@ spec:
     singular: certificatestore
   scope: Namespaced
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the eraser API has been deprecated. Please migrate
+      to v1beta1.
+    name: v1alpha1
     schema:
       openAPIV3Schema:
         description: CertificateStore is the Schema for the certificatestores API
@@ -35,11 +38,11 @@ spec:
             description: CertificateStoreSpec defines the desired state of CertificateStore
             properties:
               parameters:
-                description: Parameters of the store
+                description: Parameters of the certificate store
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               provider:
-                description: Name of the of the certificate store provider
+                description: Name of the certificate store provider
                 type: string
             type: object
           status:
@@ -47,4 +50,42 @@ spec:
             type: object
         type: object
     served: true
-    storage: true
\ No newline at end of file
+    storage: false
+    subresources:
+      status: {}
+  - name: v1beta1
+    schema:
+      openAPIV3Schema:
+        description: CertificateStore is the Schema for the certificatestores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: CertificateStoreSpec defines the desired state of CertificateStore
+            properties:
+              parameters:
+                description: Parameters of the certificate store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              provider:
+                description: Name of the certificate store provider
+                type: string
+            type: object
+          status:
+            description: CertificateStoreStatus defines the observed state of CertificateStore
+            type: object
+        type: object
+    served: true
+    storage: true
+    subresources:
+      status: {}
diff --git a/config/crd/bases/config.ratify.deislabs.io_certificatestores.yaml b/config/crd/bases/config.ratify.deislabs.io_certificatestores.yaml
index 2a77700..40292c1 100644
--- a/config/crd/bases/config.ratify.deislabs.io_certificatestores.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_certificatestores.yaml
@@ -15,7 +15,10 @@ spec:
     singular: certificatestore
   scope: Namespaced
   versions:
-  - name: v1alpha1
+  - deprecated: true
+    deprecationWarning: v1alpha1 of the CertificateStore API has been deprecated.
+      Please migrate to v1beta1.
+    name: v1alpha1
     schema:
       openAPIV3Schema:
         description: CertificateStore is the Schema for the certificatestores API
@@ -36,7 +39,43 @@ spec:
             description: CertificateStoreSpec defines the desired state of CertificateStore
             properties:
               parameters:
-                description: Parameters of the store
+                description: Parameters of the certificate store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+              provider:
+                description: Name of the certificate store provider
+                type: string
+            type: object
+          status:
+            description: CertificateStoreStatus defines the observed state of CertificateStore
+            type: object
+        type: object
+    served: true
+    storage: false
+    subresources:
+      status: {}
+  - name: v1beta1
+    schema:
+      openAPIV3Schema:
+        description: CertificateStore is the Schema for the certificatestores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: CertificateStoreSpec defines the desired state of CertificateStore
+            properties:
+              parameters:
+                description: Parameters of the certificate store
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               provider:
@@ -49,3 +88,5 @@ spec:
         type: object
     served: true
     storage: true
+    subresources:
+      status: {}
diff --git a/pkg/common/plugin/download_test.go b/pkg/common/plugin/download_test.go
index 5abc3b8..d5dbba0 100644
--- a/pkg/common/plugin/download_test.go
+++ b/pkg/common/plugin/download_test.go
@@ -19,7 +19,7 @@ import (
 	"encoding/json"
 	"testing"
 
-	"github.com/deislabs/ratify/api/v1alpha1"
+	"github.com/deislabs/ratify/api/v1beta1"
 )
 
 func TestParsePluginSource_HandlesJSON(t *testing.T) {
@@ -56,10 +56,10 @@ func TestParsePluginSource_HandlesJSON(t *testing.T) {
 }
 
 func TestParsePluginSource_HandlesCRD(t *testing.T) {
-	verifierConfig := v1alpha1.VerifierSpec{
+	verifierConfig := v1beta1.VerifierSpec{
 		Name:          "dynamic",
 		ArtifactTypes: "sbom/example",
-		Source: &v1alpha1.PluginSource{
+		Source: &v1beta1.PluginSource{
 			Artifact: "wabbitnetworks.azurecr.io/test/sample-plugin:v1",
 		},
 	}
diff --git a/pkg/controllers/certificatestore_controller.go b/pkg/controllers/certificatestore_controller.go
index 2ba9c8a..0582384 100644
--- a/pkg/controllers/certificatestore_controller.go
+++ b/pkg/controllers/certificatestore_controller.go
@@ -22,7 +22,7 @@ import (
 	"encoding/json"
 	"fmt"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"github.com/deislabs/ratify/pkg/certificateprovider/azurekeyvault"
 	"github.com/deislabs/ratify/pkg/certificateprovider/inline"
 
@@ -60,7 +60,7 @@ func (r *CertificateStoreReconciler) Reconcile(ctx context.Context, req ctrl.Req
 	logger := logrus.WithContext(ctx)
 
 	var resource = req.Name
-	var certStore configv1alpha1.CertificateStore
+	var certStore configv1beta1.CertificateStore
 
 	logger.Infof("reconciling certificate store '%v'", resource)
 
@@ -99,7 +99,7 @@ func (r *CertificateStoreReconciler) Reconcile(ctx context.Context, req ctrl.Req
 		logger.Infof("%v certificates fetched for certificate store %v", len(certificates), resource)
 	default:
 
-		return ctrl.Result{}, fmt.Errorf("Unknown provider value %v defined in certificate store %v", certStore.Spec.Provider, resource)
+		return ctrl.Result{}, fmt.Errorf("unknown provider value %v defined in certificate store %v", certStore.Spec.Provider, resource)
 	}
 
 	// returning empty result and no error to indicate we’ve successfully reconciled this object
@@ -114,11 +114,11 @@ func GetCertificatesMap() map[string][]*x509.Certificate {
 // SetupWithManager sets up the controller with the Manager.
 func (r *CertificateStoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
-		For(&configv1alpha1.CertificateStore{}).
+		For(&configv1beta1.CertificateStore{}).
 		Complete(r)
 }
 
-func getCertStoreConfig(spec configv1alpha1.CertificateStoreSpec) (map[string]string, error) {
+func getCertStoreConfig(spec configv1beta1.CertificateStoreSpec) (map[string]string, error) {
 	attributes := map[string]string{}
 
 	if string(spec.Parameters.Raw) == "" {
diff --git a/pkg/controllers/certificatestore_controller_test.go b/pkg/controllers/certificatestore_controller_test.go
index f21deb9..e93d770 100644
--- a/pkg/controllers/certificatestore_controller_test.go
+++ b/pkg/controllers/certificatestore_controller_test.go
@@ -18,7 +18,7 @@ package controllers
 import (
 	"testing"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -26,7 +26,7 @@ func TestGetCertStoreConfig_ValidConfig(t *testing.T) {
 	var parametersString = "{\"certificates\":\"array:\\n  - |\\n    certificateName: wabbit-networks-io\\n    certificateVersion: 97a1545d893344079ce57699c8810590\\n\",\"clientID\":\"sampleClientID\",\"keyvaultName\":\"sampleKeyVault\",\"tenantID\":\"sampleTenantID\"}"
 	var certStoreParameters = []byte(parametersString)
 
-	spec := configv1alpha1.CertificateStoreSpec{
+	spec := configv1beta1.CertificateStoreSpec{
 		Provider: "azurekeyvault",
 		Parameters: runtime.RawExtension{
 			Raw: certStoreParameters,
@@ -51,7 +51,7 @@ func TestGetCertStoreConfig_EmptyStringError(t *testing.T) {
 	var parametersString = ""
 	var certStoreParameters = []byte(parametersString)
 
-	spec := configv1alpha1.CertificateStoreSpec{
+	spec := configv1beta1.CertificateStoreSpec{
 		Provider: "azurekeyvault",
 		Parameters: runtime.RawExtension{
 			Raw: certStoreParameters,
diff --git a/pkg/controllers/store_controller_test.go b/pkg/controllers/store_controller_test.go
index 0a21e3c..167744b 100644
--- a/pkg/controllers/store_controller_test.go
+++ b/pkg/controllers/store_controller_test.go
@@ -18,14 +18,14 @@ package controllers
 import (
 	"testing"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	"github.com/deislabs/ratify/pkg/referrerstore"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
 func TestStoreAdd_EmptyParameter(t *testing.T) {
 	resetStoreMap()
-	var testStoreSpec = configv1alpha1.StoreSpec{
+	var testStoreSpec = configv1beta1.StoreSpec{
 		Name: "oras",
 	}
 
@@ -69,7 +69,7 @@ func TestStore_UpdateAndDelete(t *testing.T) {
 	}
 
 	// modify the Store
-	var updatedSpec = configv1alpha1.StoreSpec{
+	var updatedSpec = configv1beta1.StoreSpec{
 		Name: "oras",
 	}
 
@@ -93,11 +93,11 @@ func resetStoreMap() {
 	StoreMap = map[string]referrerstore.ReferrerStore{}
 }
 
-func getOrasStoreSpec() configv1alpha1.StoreSpec {
+func getOrasStoreSpec() configv1beta1.StoreSpec {
 	var parametersString = "{\"authProvider\":{\"name\":\"k8Secrets\",\"secrets\":[{\"secretName\":\"myregistrykey\"}]},\"cosignEnabled\":false,\"useHttp\":false}"
 	var storeParameters = []byte(parametersString)
 
-	return configv1alpha1.StoreSpec{
+	return configv1beta1.StoreSpec{
 		Name: "oras",
 		Parameters: runtime.RawExtension{
 			Raw: storeParameters,
diff --git a/pkg/controllers/verifier_controller_test.go b/pkg/controllers/verifier_controller_test.go
index 98f4f8a..dfffb0f 100644
--- a/pkg/controllers/verifier_controller_test.go
+++ b/pkg/controllers/verifier_controller_test.go
@@ -19,7 +19,7 @@ import (
 	"os"
 	"testing"
 
-	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	configv1beta1 "github.com/deislabs/ratify/api/v1beta1"
 	vr "github.com/deislabs/ratify/pkg/verifier"
 	"k8s.io/apimachinery/pkg/runtime"
 )
@@ -33,7 +33,7 @@ func TestMain(m *testing.M) {
 
 func TestVerifierAdd_EmptyParameter(t *testing.T) {
 	resetVerifierMap()
-	var testVerifierSpec = configv1alpha1.VerifierSpec{
+	var testVerifierSpec = configv1beta1.VerifierSpec{
 		Name:          "notaryv2",
 		ArtifactTypes: "application/vnd.cncf.notary.signature",
 	}
@@ -100,10 +100,10 @@ func resetVerifierMap() {
 	VerifierMap = map[string]vr.ReferenceVerifier{}
 }
 
-func getLicenseCheckerFromParam(parametersString string) configv1alpha1.VerifierSpec {
+func getLicenseCheckerFromParam(parametersString string) configv1beta1.VerifierSpec {
 	var allowedLicenses = []byte(parametersString)
 
-	return configv1alpha1.VerifierSpec{
+	return configv1beta1.VerifierSpec{
 		Name:          "licensechecker",
 		ArtifactTypes: "application/vnd.ratify.spdx.v0",
 		Parameters: runtime.RawExtension{
@@ -112,7 +112,7 @@ func getLicenseCheckerFromParam(parametersString string) configv1alpha1.Verifier
 	}
 }
 
-func getDefaultLicenseCheckerSpec() configv1alpha1.VerifierSpec {
+func getDefaultLicenseCheckerSpec() configv1beta1.VerifierSpec {
 	var parametersString = "{\"allowedLicenses\":[\"MIT\",\"Apache\"]}"
 	return getLicenseCheckerFromParam(parametersString)
 }
diff --git a/test/bats/azure-test.bats b/test/bats/azure-test.bats
index b519550..51e978d 100644
--- a/test/bats/azure-test.bats
+++ b/test/bats/azure-test.bats
@@ -7,7 +7,7 @@ WAIT_TIME=60
 SLEEP_TIME=1
 
 @test "dynamic plugins enabled test" {
-    # only run this test against a live cluster 
+    # only run this test against a live cluster
 
     # ensure that the chart deployment is reset to a clean state for other tests
     teardown() {
@@ -22,7 +22,7 @@ SLEEP_TIME=1
     sleep 5
     latestpod=$(kubectl -n gatekeeper-system get pod -l=app.kubernetes.io/name=ratify --sort-by=.metadata.creationTimestamp -o=name | tail -n 1)
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_dynamic.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_dynamic.yaml
     sleep 5
 
     # parse the logs for the newly created ratify pod
@@ -84,12 +84,12 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_partial_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_partial_licensechecker.yaml
     sleep 5
     run kubectl run license-checker --namespace default --image=wabbitnetworks.azurecr.io/test/license-checker-image:v1
     assert_failure
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
     # wait for the httpserver cache to be invalidated
     sleep 15
     run kubectl run license-checker2 --namespace default --image=wabbitnetworks.azurecr.io/test/license-checker-image:v1
@@ -97,7 +97,7 @@ SLEEP_TIME=1
 }
 
 @test "sbom verifier test" {
-     teardown() {
+    teardown() {
         echo "cleaning up"
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod sbom --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod sbom2 --namespace default --force --ignore-not-found=true'
@@ -110,7 +110,7 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_sbom.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_sbom.yaml
     sleep 5
     run kubectl run sbom --namespace default --image=wabbitnetworks.azurecr.io/test/sbom-image:signed
     assert_success
@@ -140,7 +140,7 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator.yaml
     sleep 5
     # TODO
     # It's best to use an image with individual artifact types vs an all-in-one so any failures can be isolated.
@@ -148,7 +148,7 @@ SLEEP_TIME=1
     run kubectl run schemavalidator --namespace default --image=wabbitnetworks.azurecr.io/test/all-in-one-image:signed
     assert_success
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator_bad.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator_bad.yaml
     # wait for the httpserver cache to be invalidated
     sleep 15
     run kubectl run schemavalidator2 --namespace default --image=wabbitnetworks.azurecr.io/test/all-in-one-image:signed
@@ -172,13 +172,13 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_cosign.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_cosign.yaml
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_sbom.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_sbom.yaml
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator.yaml
     sleep 5
 
     run kubectl run all-in-one --namespace default --image=wabbitnetworks.azurecr.io/test/all-in-one-image:signed
@@ -192,7 +192,7 @@ SLEEP_TIME=1
     }
 
     echo "adding license checker, delete notary verifier and validate deployment fails due to missing notary verifier"
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
     assert_success
     run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notary
     assert_success
@@ -202,7 +202,7 @@ SLEEP_TIME=1
     assert_failure
 
     echo "Add notary verifier and validate deployment succeeds"
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_notary_certstore.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_notary_certstore.yaml
     assert_success
 
     # wait for the httpserver cache to be invalidated
@@ -246,7 +246,7 @@ SLEEP_TIME=1
     start=$(date --iso-8601=seconds)
     latestpod=$(kubectl -n gatekeeper-system get pod -l=app.kubernetes.io/name=ratify --sort-by=.metadata.creationTimestamp -o=name | tail -n 1)
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_dynamic.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_dynamic.yaml
     sleep 5
 
     run bash -c "kubectl -n gatekeeper-system logs $latestpod --since-time=$start | grep 'dynamic plugins are currently disabled'"
diff --git a/test/bats/test.bats b/test/bats/test.bats
index af65dee..804e0f2 100644
--- a/test/bats/test.bats
+++ b/test/bats/test.bats
@@ -6,6 +6,22 @@ BATS_TESTS_DIR=${BATS_TESTS_DIR:-test/bats/tests}
 WAIT_TIME=60
 SLEEP_TIME=1
 
+@test "crd version test" {
+    run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notary
+    assert_success
+    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_notary.yaml
+    assert_success
+    run bash -c "kubectl get verifiers.config.ratify.deislabs.io/verifier-notary -o yaml | grep 'apiVersion: config.ratify.deislabs.io/v1beta1'"
+    assert_success
+
+    run kubectl delete stores.config.ratify.deislabs.io/store-oras
+    assert_success
+    run kubectl apply -f ./config/samples/config_v1alpha1_store_oras_http.yaml
+    assert_success
+    run bash -c "kubectl get stores.config.ratify.deislabs.io/store-oras -o yaml | grep 'apiVersion: config.ratify.deislabs.io/v1beta1'"
+    assert_success
+}
+
 @test "notary test" {
     teardown() {
         echo "cleaning up"
@@ -54,20 +70,20 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo-keyless --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-cosign --namespace default --ignore-not-found=true'
     }
-     # update the config to use the keyless verifier since ratify doesn't support multiple verifiers of same type
-    sed -i 's/\/usr\/local\/ratify-certs\/cosign\/cosign.pub/""/g' ./config/samples/config_v1alpha1_verifier_cosign.yaml
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_cosign.yaml
+    # update the config to use the keyless verifier since ratify doesn't support multiple verifiers of same type
+    sed -i 's/\/usr\/local\/ratify-certs\/cosign\/cosign.pub/""/g' ./config/samples/config_v1beta1_verifier_cosign.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_cosign.yaml
     sleep 5
 
     # use imperative command to guarantee useHttp is updated
-    run kubectl replace -f ./config/samples/config_v1alpha1_store_oras.yaml
+    run kubectl replace -f ./config/samples/config_v1beta1_store_oras.yaml
     sleep 5
 
     run kubectl run cosign-demo-keyless --namespace default --image=wabbitnetworks.azurecr.io/test/cosign-image:signed-keyless
     assert_success
 
-    sed -i 's/""/\/usr\/local\/ratify-certs\/cosign\/cosign.pub/g' ./config/samples/config_v1alpha1_verifier_cosign.yaml
-    run kubectl apply -f ./config/samples/config_v1alpha1_store_oras_http.yaml
+    sed -i 's/""/\/usr\/local\/ratify-certs\/cosign\/cosign.pub/g' ./config/samples/config_v1beta1_verifier_cosign.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_store_oras_http.yaml
 }
 
 @test "licensechecker test" {
@@ -85,12 +101,12 @@ SLEEP_TIME=1
     run kubectl apply -f ./library/default/samples/constraint.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_partial_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_partial_licensechecker.yaml
     sleep 5
     run kubectl run license-checker --namespace default --image=registry:5000/licensechecker:v0
     assert_failure
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
     # wait for the httpserver cache to be invalidated
     sleep 15
     run kubectl run license-checker2 --namespace default --image=registry:5000/licensechecker:v0
@@ -115,7 +131,7 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_sbom.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_sbom.yaml
     sleep 5
     run kubectl run sbom --namespace default --image=registry:5000/sbom:v0
     assert_success
@@ -150,7 +166,7 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator.yaml
     sleep 5
     run kubectl run schemavalidator --namespace default --image=registry:5000/schemavalidator:v0
     assert_success
@@ -158,7 +174,7 @@ SLEEP_TIME=1
     run kubectl run schemavalidator-oci-image --namespace default --image=registry:5000/schemavalidator:ociimage
     assert_success
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator_bad.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator_bad.yaml
     assert_success
     # wait for the httpserver cache to be invalidated
     sleep 15
@@ -183,15 +199,15 @@ SLEEP_TIME=1
     assert_success
     sleep 5
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_cosign.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_cosign.yaml
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_sbom.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_sbom.yaml
     sleep 5
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
 
     # Skipping test for now until expected usage/configuration of this plugin can be verified
     # sleep 5
-    # run kubectl apply -f ./config/samples/config_v1alpha1_verifier_schemavalidator.yaml
+    # run kubectl apply -f ./config/samples/config_v1beta1_verifier_schemavalidator.yaml
     # sleep 5
 
     # wait for the httpserver cache to be invalidated
@@ -207,7 +223,7 @@ SLEEP_TIME=1
     }
 
     echo "adding license checker, delete notary verifier and validate deployment fails due to missing notary verifier"
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_complete_licensechecker.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_complete_licensechecker.yaml
     assert_success
     run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notary
     assert_success
@@ -217,7 +233,7 @@ SLEEP_TIME=1
     assert_failure
 
     echo "Add notary verifier and validate deployment succeeds"
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_notary.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_notary.yaml
     assert_success
 
     # wait for the httpserver cache to be invalidated
@@ -262,7 +278,7 @@ SLEEP_TIME=1
     start=$(date --iso-8601=seconds)
     latestpod=$(kubectl -n gatekeeper-system get pod -l=app.kubernetes.io/name=ratify --sort-by=.metadata.creationTimestamp -o=name | tail -n 1)
 
-    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_dynamic.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_verifier_dynamic.yaml
     sleep 5
 
     run bash -c "kubectl -n gatekeeper-system logs $latestpod --since-time=$start | grep 'dynamic plugins are currently disabled'"
@@ -293,7 +309,7 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo-alternate --namespace default --force --ignore-not-found=true'
 
         # restore the original notary verifier for other tests
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f ./config/samples/config_v1alpha1_verifier_notary.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f ./config/samples/config_v1beta1_verifier_notary.yaml'
     }
 
     # configure the default template/constraint
@@ -308,7 +324,7 @@ SLEEP_TIME=1
 
     # add the alternate certificate as an inline certificate store
     cat <<EOF | kubectl apply -f -
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: CertificateStore
 metadata:
   name: certstore-inline
@@ -321,7 +337,7 @@ EOF
 
     # configure the notary verifier to use the inline certificate store
     cat <<EOF | kubectl apply -f -
-apiVersion: config.ratify.deislabs.io/v1alpha1
+apiVersion: config.ratify.deislabs.io/v1beta1
 kind: Verifier
 metadata:
   name: verifier-notary
@@ -366,7 +382,7 @@ EOF
     assert_success
     sleep 5
     # apply store CRD with k8 secret auth provier enabled
-    run kubectl apply -f ./config/samples/config_v1alpha1_store_oras_k8secretAuth.yaml
+    run kubectl apply -f ./config/samples/config_v1beta1_store_oras_k8secretAuth.yaml
     assert_success
     sleep 5
     run kubectl run demo --namespace default --image=registry:5000/notation:signed