diff --git a/kube-client/src/api/mod.rs b/kube-client/src/api/mod.rs
index 24088e71a..cf814fd98 100644
--- a/kube-client/src/api/mod.rs
+++ b/kube-client/src/api/mod.rs
@@ -37,7 +37,7 @@ pub use kube_core::{
     watch::WatchEvent,
     Resource, ResourceExt,
 };
-use kube_core::{DynamicResourceScope, NamespaceResourceScope};
+use kube_core::{resource, DynamicResourceScope, NamespaceResourceScope};
 pub use params::{
     DeleteParams, GetParams, ListParams, Patch, PatchParams, PostParams, Preconditions, PropagationPolicy,
     ValidationDirective, VersionMatch, WatchParams,
@@ -66,7 +66,7 @@ pub struct Api<K> {
 /// Api constructors for Resource implementors with custom DynamicTypes
 ///
 /// This generally means resources created via [`DynamicObject`](crate::api::DynamicObject).
-impl<K: Resource> Api<K> {
+impl<K: resource::Typed> Api<K> {
     /// Cluster level resources, or resources viewed across all namespaces
     ///
     /// This function accepts `K::DynamicType` so it can be used with dynamic resources.
@@ -131,9 +131,9 @@ impl<K: Resource> Api<K> {
 /// Api constructors for Resource implementors with Default DynamicTypes
 ///
 /// This generally means structs implementing `k8s_openapi::Resource`.
-impl<K: Resource> Api<K>
+impl<K: resource::Typed> Api<K>
 where
-    <K as Resource>::DynamicType: Default,
+    <K as resource::Typed>::DynamicType: Default,
 {
     /// Cluster level resources, or resources viewed across all namespaces
     ///
diff --git a/kube-client/src/client/client_ext.rs b/kube-client/src/client/client_ext.rs
index 48704ea07..da1b86bcc 100644
--- a/kube-client/src/client/client_ext.rs
+++ b/kube-client/src/client/client_ext.rs
@@ -1,10 +1,7 @@
 use crate::{Client, Error, Result};
 use k8s_openapi::api::core::v1::Namespace as k8sNs;
 use kube_core::{
-    object::ObjectList,
-    params::{GetParams, ListParams},
-    request::Request,
-    ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope, Resource,
+    object::ObjectList, params::{GetParams, ListParams}, request::Request, resource, ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope, Resource
 };
 use serde::{de::DeserializeOwned, Serialize};
 use std::fmt::Debug;
@@ -174,8 +171,8 @@ impl Client {
     /// ```
     pub async fn get<K>(&self, name: &str, scope: &impl ObjectUrl<K>) -> Result<K>
     where
-        K: Resource + Serialize + DeserializeOwned + Clone + Debug,
-        <K as Resource>::DynamicType: Default,
+        K: resource::Typed + Serialize + DeserializeOwned + Clone + Debug,
+        <K as resource::Typed>::DynamicType: Default,
     {
         let mut req = Request::new(scope.url_path())
             .get(name, &GetParams::default())
@@ -184,7 +181,7 @@ impl Client {
         self.request::<K>(req).await
     }
 
-    /// List instances of a `Resource` implementing type `K` at the specified scope.
+    /// List instances of a [resource](resource::Typed) implementing type `K` at the specified scope.
     ///
     /// ```no_run
     /// # use k8s_openapi::api::core::v1::Pod;
@@ -205,8 +202,8 @@ impl Client {
     /// ```
     pub async fn list<K>(&self, lp: &ListParams, scope: &impl CollectionUrl<K>) -> Result<ObjectList<K>>
     where
-        K: Resource + Serialize + DeserializeOwned + Clone + Debug,
-        <K as Resource>::DynamicType: Default,
+        K: resource::Typed + Serialize + DeserializeOwned + Clone + Debug,
+        <K as resource::Typed>::DynamicType: Default,
     {
         let mut req = Request::new(scope.url_path())
             .list(lp)
diff --git a/kube-core/src/dynamic.rs b/kube-core/src/dynamic.rs
index ebaa7e3a6..78c14bad7 100644
--- a/kube-core/src/dynamic.rs
+++ b/kube-core/src/dynamic.rs
@@ -4,7 +4,7 @@
 pub use crate::discovery::ApiResource;
 use crate::{
     metadata::TypeMeta,
-    resource::{DynamicResourceScope, Resource},
+    resource::{self, DynamicResourceScope, Resource},
 };
 
 use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
@@ -75,7 +75,7 @@ impl DynamicObject {
     }
 }
 
-impl Resource for DynamicObject {
+impl resource::Typed for DynamicObject {
     type DynamicType = ApiResource;
     type Scope = DynamicResourceScope;
 
@@ -98,7 +98,9 @@ impl Resource for DynamicObject {
     fn plural(dt: &ApiResource) -> Cow<'_, str> {
         dt.plural.as_str().into()
     }
+}
 
+impl Resource for DynamicObject {
     fn meta(&self) -> &ObjectMeta {
         &self.metadata
     }
diff --git a/kube-core/src/lib.rs b/kube-core/src/lib.rs
index 4e87ed752..2a64049b0 100644
--- a/kube-core/src/lib.rs
+++ b/kube-core/src/lib.rs
@@ -41,7 +41,7 @@ pub mod params;
 pub mod request;
 pub use request::Request;
 
-mod resource;
+pub mod resource;
 pub use resource::{
     api_version_from_group_version, ClusterResourceScope, DynamicResourceScope, NamespaceResourceScope,
     Resource, ResourceExt, ResourceScope, SubResourceScope,
diff --git a/kube-core/src/metadata.rs b/kube-core/src/metadata.rs
index 67edf6e16..79db7896b 100644
--- a/kube-core/src/metadata.rs
+++ b/kube-core/src/metadata.rs
@@ -4,7 +4,7 @@ use std::{borrow::Cow, marker::PhantomData};
 pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::{ListMeta, ObjectMeta};
 use serde::{Deserialize, Serialize};
 
-use crate::{DynamicObject, Resource};
+use crate::{resource, DynamicObject, Resource};
 
 /// Type information that is flattened into every kubernetes object
 #[derive(Deserialize, Serialize, Clone, Default, Debug, Eq, PartialEq, Hash)]
@@ -146,7 +146,7 @@ impl PartialObjectMetaExt for ObjectMeta {
     }
 }
 
-impl<K: Resource> Resource for PartialObjectMeta<K> {
+impl<K: resource::Typed> resource::Typed for PartialObjectMeta<K> {
     type DynamicType = K::DynamicType;
     type Scope = K::Scope;
 
@@ -165,7 +165,9 @@ impl<K: Resource> Resource for PartialObjectMeta<K> {
     fn plural(dt: &Self::DynamicType) -> Cow<'_, str> {
         K::plural(dt)
     }
+}
 
+impl<K: Resource> Resource for PartialObjectMeta<K> {
     fn meta(&self) -> &ObjectMeta {
         &self.metadata
     }
diff --git a/kube-core/src/object.rs b/kube-core/src/object.rs
index 2e51b3f64..847bbe5cd 100644
--- a/kube-core/src/object.rs
+++ b/kube-core/src/object.rs
@@ -2,7 +2,7 @@
 use crate::{
     discovery::ApiResource,
     metadata::{ListMeta, ObjectMeta, TypeMeta},
-    resource::{DynamicResourceScope, Resource},
+    resource::{self, DynamicResourceScope, Resource},
 };
 use serde::{Deserialize, Deserializer, Serialize};
 use std::borrow::Cow;
@@ -241,7 +241,7 @@ where
     }
 }
 
-impl<P, U> Resource for Object<P, U>
+impl<P, U> resource::Typed for Object<P, U>
 where
     P: Clone,
     U: Clone,
@@ -268,7 +268,13 @@ where
     fn api_version(dt: &ApiResource) -> Cow<'_, str> {
         dt.api_version.as_str().into()
     }
+}
 
+impl<P, U> Resource for Object<P, U>
+where
+    P: Clone,
+    U: Clone,
+{
     fn meta(&self) -> &ObjectMeta {
         &self.metadata
     }
diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs
index 3ab1d88df..17b9ac8b6 100644
--- a/kube-core/src/resource.rs
+++ b/kube-core/src/resource.rs
@@ -1,3 +1,5 @@
+//! Types representing Kubernetes resource objects.
+
 pub use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
 use k8s_openapi::{
     api::core::v1::ObjectReference,
@@ -12,19 +14,9 @@ pub use k8s_openapi::{ClusterResourceScope, NamespaceResourceScope, ResourceScop
 pub struct DynamicResourceScope {}
 impl ResourceScope for DynamicResourceScope {}
 
-/// An accessor trait for a kubernetes Resource.
-///
-/// This is for a subset of Kubernetes type that do not end in `List`.
-/// These types, using [`ObjectMeta`], SHOULD all have required properties:
-/// - `.metadata`
-/// - `.metadata.name`
-///
-/// And these optional properties:
-/// - `.metadata.namespace`
-/// - `.metadata.resource_version`
-///
-/// This avoids a bunch of the unnecessary unwrap mechanics for apps.
-pub trait Resource {
+/// Represents a type that can either statically imply a Kubernetes versioned resource type
+/// or resolve into one given specific data.
+pub trait Typed {
     /// Type information for types that do not know their resource information at compile time.
     ///
     /// Types that know their metadata at compile time should select `DynamicType = ()`.
@@ -72,7 +64,21 @@ pub trait Resource {
             plural = plural
         )
     }
+}
 
+/// An accessor trait for a kubernetes Resource.
+///
+/// This is for a subset of Kubernetes type that do not end in `List`.
+/// These types, using [`ObjectMeta`], SHOULD all have required properties:
+/// - `.metadata`
+/// - `.metadata.name`
+///
+/// And these optional properties:
+/// - `.metadata.namespace`
+/// - `.metadata.resource_version`
+///
+/// This avoids a bunch of the unnecessary unwrap mechanics for apps.
+pub trait Resource: Typed {
     /// Metadata that all persisted resources must have
     fn meta(&self) -> &ObjectMeta;
     /// Metadata that all persisted resources must have
@@ -166,8 +172,7 @@ pub fn api_version_from_group_version<'a>(group: Cow<'a, str>, version: Cow<'a,
     output
 }
 
-/// Implement accessor trait for any ObjectMeta-using Kubernetes Resource
-impl<K, S> Resource for K
+impl<K, S> Typed for K
 where
     K: k8s_openapi::Metadata<Ty = ObjectMeta>,
     K: k8s_openapi::Resource<Scope = S>,
@@ -194,7 +199,14 @@ where
     fn plural(_: &()) -> Cow<'_, str> {
         K::URL_PATH_SEGMENT.into()
     }
+}
 
+/// Implement accessor trait for any ObjectMeta-using Kubernetes Resource
+impl<K, S> Resource for K
+where
+    K: k8s_openapi::Metadata<Ty = ObjectMeta>,
+    K: k8s_openapi::Resource<Scope = S>,
+{
     fn meta(&self) -> &ObjectMeta {
         self.metadata()
     }
diff --git a/kube-runtime/src/controller/mod.rs b/kube-runtime/src/controller/mod.rs
index 5c36b38e7..9dd2d2efe 100644
--- a/kube-runtime/src/controller/mod.rs
+++ b/kube-runtime/src/controller/mod.rs
@@ -18,7 +18,7 @@ use futures::{
     future::{self, BoxFuture},
     stream, FutureExt, Stream, StreamExt, TryFuture, TryFutureExt, TryStream, TryStreamExt,
 };
-use kube_client::api::{Api, DynamicObject, Resource};
+use kube_client::{api::{Api, DynamicObject, Resource}, core::resource};
 use pin_project::pin_project;
 use serde::de::DeserializeOwned;
 use std::{
@@ -149,13 +149,13 @@ where
 fn trigger_others<S, K, I>(
     stream: S,
     mapper: impl Fn(S::Ok) -> I + Sync + Send + 'static,
-    dyntype: <S::Ok as Resource>::DynamicType,
+    dyntype: <S::Ok as resource::Typed>::DynamicType,
 ) -> impl Stream<Item = Result<ReconcileRequest<K>, S::Error>>
 where
     // Input stream has items as some Resource (via Controller::watches)
     S: TryStream,
     S::Ok: Resource,
-    <S::Ok as Resource>::DynamicType: Clone,
+    <S::Ok as resource::Typed>::DynamicType: Clone,
     // Output stream is requests for the root type K
     K: Resource,
     K::DynamicType: Clone,
@@ -212,12 +212,12 @@ where
 pub fn trigger_owners<KOwner, S>(
     stream: S,
     owner_type: KOwner::DynamicType,
-    child_type: <S::Ok as Resource>::DynamicType,
+    child_type: <S::Ok as resource::Typed>::DynamicType,
 ) -> impl Stream<Item = Result<ReconcileRequest<KOwner>, S::Error>>
 where
     S: TryStream,
     S::Ok: Resource,
-    <S::Ok as Resource>::DynamicType: Clone,
+    <S::Ok as resource::Typed>::DynamicType: Clone,
     KOwner: Resource,
     KOwner::DynamicType: Clone,
 {