diff --git a/garnet/bin/cmc/src/cml.rs b/garnet/bin/cmc/src/cml.rs
index de360c5bc14d903585ef761ffc20728ff31661b9..5ed1aa768bfab422dbe9f427b01797d2ecd05c59 100644
--- a/garnet/bin/cmc/src/cml.rs
+++ b/garnet/bin/cmc/src/cml.rs
@@ -7,8 +7,6 @@ use regex::Regex;
 use serde_derive::Deserialize;
 use serde_json::{Map, Value};
 
-pub const DIRECTORY: &str = "directory";
-pub const SERVICE: &str = "service";
 lazy_static! {
     pub static ref CHILD_RE: Regex = Regex::new(r"^#([A-Za-z0-9\-_]+)$").unwrap();
     pub static ref FROM_RE: Regex = Regex::new(r"^(realm|self|#[A-Za-z0-9\-_]+)$").unwrap();
diff --git a/garnet/bin/cmc/src/compile.rs b/garnet/bin/cmc/src/compile.rs
index fa00342a04244148c3d835ba8238348b38bf6a97..35e5eb83198c483c3b36c7b42864e6a814d4b435 100644
--- a/garnet/bin/cmc/src/compile.rs
+++ b/garnet/bin/cmc/src/compile.rs
@@ -89,9 +89,9 @@ fn compile_cml(document: cml::Document) -> Result<cm::Document, Error> {
 fn translate_use(use_in: &Vec<cml::Use>) -> Result<Vec<cm::Use>, Error> {
     let mut out_uses = vec![];
     for use_ in use_in {
-        let (r#type, source_path) = extract_source_capability(use_)?;
-        let target_path = extract_target_path(use_, &source_path);
-        out_uses.push(cm::Use { r#type, source_path, target_path });
+        let capability = extract_capability(use_)?;
+        let target_path = extract_target_path(use_, &capability)?;
+        out_uses.push(cm::Use { capability, target_path });
     }
     Ok(out_uses)
 }
@@ -99,10 +99,10 @@ fn translate_use(use_in: &Vec<cml::Use>) -> Result<Vec<cm::Use>, Error> {
 fn translate_expose(expose_in: &Vec<cml::Expose>) -> Result<Vec<cm::Expose>, Error> {
     let mut out_exposes = vec![];
     for expose in expose_in.iter() {
-        let (r#type, source_path) = extract_source_capability(expose)?;
+        let capability = extract_capability(expose)?;
         let source = extract_source(expose)?;
-        let target_path = extract_target_path(expose, &source_path);
-        out_exposes.push(cm::Expose { r#type, source_path, source, target_path });
+        let target_path = extract_target_path(expose, &capability)?;
+        out_exposes.push(cm::Expose { capability, source, target_path });
     }
     Ok(out_exposes)
 }
@@ -110,10 +110,10 @@ fn translate_expose(expose_in: &Vec<cml::Expose>) -> Result<Vec<cm::Expose>, Err
 fn translate_offer(offer_in: &Vec<cml::Offer>) -> Result<Vec<cm::Offer>, Error> {
     let mut out_offers = vec![];
     for offer in offer_in.iter() {
-        let (r#type, source_path) = extract_source_capability(offer)?;
+        let capability = extract_capability(offer)?;
         let source = extract_source(offer)?;
-        let targets = extract_targets(offer, &source_path)?;
-        out_offers.push(cm::Offer { r#type, source_path, source, targets });
+        let targets = extract_targets(offer, &capability)?;
+        out_offers.push(cm::Offer { capability, source, targets });
     }
     Ok(out_offers)
 }
@@ -144,15 +144,11 @@ where
     }
     let ret = if from.starts_with("#") {
         let (_, child_name) = from.split_at(1);
-        cm::Source {
-            realm: None,
-            myself: None,
-            child: Some(cm::ChildId { name: child_name.to_string() }),
-        }
+        cm::Source::Child(cm::ChildId { name: child_name.to_string() })
     } else if from == "realm" {
-        cm::Source { realm: Some(cm::RealmId {}), myself: None, child: None }
+        cm::Source::Realm(cm::RealmId {})
     } else if from == "self" {
-        cm::Source { realm: None, myself: Some(cm::SelfId {}), child: None }
+        cm::Source::Myself(cm::SelfId {})
     } else {
         return Err(Error::internal(format!("invalid \"from\": {}", from)));
     };
@@ -160,10 +156,13 @@ where
 }
 
 // Extract "targets" from "offer.to".
-fn extract_targets(in_obj: &cml::Offer, source_path: &str) -> Result<Vec<cm::Target>, Error> {
+fn extract_targets(
+    in_obj: &cml::Offer,
+    capability: &cm::Capability,
+) -> Result<Vec<cm::Target>, Error> {
     let mut out_targets = vec![];
     for to in in_obj.to.iter() {
-        let target_path = extract_target_path(to, source_path);
+        let target_path = extract_target_path(to, capability)?;
         let caps = match cml::CHILD_RE.captures(&to.dest) {
             Some(c) => Ok(c),
             None => Err(Error::internal(format!("invalid \"dest\": {}", to.dest))),
@@ -174,29 +173,33 @@ fn extract_targets(in_obj: &cml::Offer, source_path: &str) -> Result<Vec<cm::Tar
     Ok(out_targets)
 }
 
-fn extract_source_capability<T>(in_obj: &T) -> Result<(String, String), Error>
+fn extract_capability<T>(in_obj: &T) -> Result<cm::Capability, Error>
 where
     T: cml::CapabilityClause,
 {
-    let (capability, source_path) = if let Some(p) = in_obj.service() {
-        (cml::SERVICE.to_string(), p.clone())
+    let capability = if let Some(p) = in_obj.service() {
+        cm::Capability::Service(cm::Service { path: p.clone() })
     } else if let Some(p) = in_obj.directory() {
-        (cml::DIRECTORY.to_string(), p.clone())
+        cm::Capability::Directory(cm::Directory { path: p.clone() })
     } else {
-        return Err(Error::internal(format!("no source path")));
+        return Err(Error::internal(format!("no capability")));
     };
-    Ok((capability, source_path))
+    Ok(capability)
 }
 
-fn extract_target_path<T>(in_obj: &T, source_path: &str) -> String
+fn extract_target_path<T>(in_obj: &T, capability: &cm::Capability) -> Result<String, Error>
 where
     T: cml::AsClause,
 {
-    if let Some(as_) = in_obj.r#as() {
+    let out = if let Some(as_) = in_obj.r#as() {
         as_.clone()
     } else {
-        source_path.to_string()
-    }
+        match capability {
+            cm::Capability::Service(s) => s.path.clone(),
+            cm::Capability::Directory(d) => d.path.clone(),
+        }
+    };
+    Ok(out)
 }
 
 #[cfg(test)]
@@ -269,13 +272,19 @@ mod tests {
             output = r#"{
     "uses": [
         {
-            "type": "service",
-            "source_path": "/fonts/CoolFonts",
+            "capability": {
+                "service": {
+                    "path": "/fonts/CoolFonts"
+                }
+            },
             "target_path": "/svc/fuchsia.fonts.Provider"
         },
         {
-            "type": "directory",
-            "source_path": "/data/assets",
+            "capability": {
+                "directory": {
+                    "path": "/data/assets"
+                }
+            },
             "target_path": "/data/assets"
         }
     ]
@@ -301,8 +310,11 @@ mod tests {
             output = r#"{
     "exposes": [
         {
-            "type": "service",
-            "source_path": "/loggers/fuchsia.logger.Log",
+            "capability": {
+                "service": {
+                    "path": "/loggers/fuchsia.logger.Log"
+                }
+            },
             "source": {
                 "child": {
                     "name": "logger"
@@ -311,8 +323,11 @@ mod tests {
             "target_path": "/svc/fuchsia.logger.Log"
         },
         {
-            "type": "directory",
-            "source_path": "/volumes/blobfs",
+            "capability": {
+                "directory": {
+                    "path": "/volumes/blobfs"
+                }
+            },
             "source": {
                 "myself": {}
             },
@@ -365,8 +380,11 @@ mod tests {
             output = r#"{
     "offers": [
         {
-            "type": "service",
-            "source_path": "/svc/fuchsia.logger.Log",
+            "capability": {
+                "service": {
+                    "path": "/svc/fuchsia.logger.Log"
+                }
+            },
             "source": {
                 "child": {
                     "name": "logger"
@@ -384,8 +402,11 @@ mod tests {
             ]
         },
         {
-            "type": "directory",
-            "source_path": "/data/assets",
+            "capability": {
+                "directory": {
+                    "path": "/data/assets"
+                }
+            },
             "source": {
                 "realm": {}
             },
@@ -496,7 +517,7 @@ mod tests {
                         "service": "/svc/fuchsia.logger.Log",
                         "from": "#logger",
                         "to": [
-                          { "dest": "#netstack" }
+                            { "dest": "#netstack" }
                         ]
                     }
                 ],
@@ -521,15 +542,21 @@ mod tests {
     },
     "uses": [
         {
-            "type": "service",
-            "source_path": "/fonts/CoolFonts",
+            "capability": {
+                "service": {
+                    "path": "/fonts/CoolFonts"
+                }
+            },
             "target_path": "/svc/fuchsia.fonts.Provider"
         }
     ],
     "exposes": [
         {
-            "type": "directory",
-            "source_path": "/volumes/blobfs",
+            "capability": {
+                "directory": {
+                    "path": "/volumes/blobfs"
+                }
+            },
             "source": {
                 "myself": {}
             },
@@ -538,8 +565,11 @@ mod tests {
     ],
     "offers": [
         {
-            "type": "service",
-            "source_path": "/svc/fuchsia.logger.Log",
+            "capability": {
+                "service": {
+                    "path": "/svc/fuchsia.logger.Log"
+                }
+            },
             "source": {
                 "child": {
                     "name": "logger"
@@ -581,7 +611,7 @@ mod tests {
                 { "directory": "/data/assets" }
             ]
         });
-        let output = r#"{"uses":[{"type":"service","source_path":"/fonts/CoolFonts","target_path":"/svc/fuchsia.fonts.Provider"},{"type":"directory","source_path":"/data/assets","target_path":"/data/assets"}]}"#;
+        let output = r#"{"uses":[{"capability":{"service":{"path":"/fonts/CoolFonts"}},"target_path":"/svc/fuchsia.fonts.Provider"},{"capability":{"directory":{"path":"/data/assets"}},"target_path":"/data/assets"}]}"#;
         compile_test(input, &output, false);
     }
 
diff --git a/garnet/bin/cmc/src/validate.rs b/garnet/bin/cmc/src/validate.rs
index cebca274a400e33369f1e702f288848898485ef4..1ce273ee786b856b79278e2854c951c00609f13d 100644
--- a/garnet/bin/cmc/src/validate.rs
+++ b/garnet/bin/cmc/src/validate.rs
@@ -168,7 +168,8 @@ impl<'a> ValidationContext<'a> {
             if let Some(from_child) = &from_child {
                 if from_child == &to.dest {
                     return Err(Error::validate(format!(
-                        "Offer target \"{}\" is same as source", &to.dest,
+                        "Offer target \"{}\" is same as source",
+                        &to.dest,
                     )));
                 }
             }
@@ -386,13 +387,19 @@ mod tests {
             input = json!({
                 "uses": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.boot.Log",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.boot.Log"
+                            }
+                        },
                         "target_path": "/svc/fuchsia.logger.Log",
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/data/assets",
+                        "capability": {
+                            "directory": {
+                               "path": "/data/assets"
+                            }
+                        },
                         "target_path": "/data/kitten_assets",
                     }
                 ]
@@ -403,19 +410,22 @@ mod tests {
             input = json!({
                 "uses": [ {} ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /uses/0/source_path, This property is required at /uses/0/target_path, This property is required at /uses/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /uses/0/capability, This property is required at /uses/0/target_path")),
         },
         test_cm_uses_bad_type => {
             input = json!({
                 "uses": [
                     {
-                        "type": "bad",
-                        "source_path": "/svc/fuchsia.logger.Log",
+                        "capability": {
+                            "bad": {
+                               "path": "/svc/fuchsia.logger.Log"
+                            }
+                        },
                         "target_path": "/svc/fuchsia.logger.Log",
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "OneOf conditions are not met at /uses/0/capability")),
         },
 
         // exposes
@@ -423,16 +433,22 @@ mod tests {
             input = json!({
                 "exposes": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
                         "target_path": "/svc/fuchsia.ui.Scenic"
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/data/assets",
+                        "capability": {
+                            "directory": {
+                               "path": "/data/assets"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "cat_viewer"
@@ -448,14 +464,17 @@ mod tests {
             input = json!({
                 "exposes": [ {} ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /exposes/0/source, This property is required at /exposes/0/source_path, This property is required at /exposes/0/target_path, This property is required at /exposes/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /exposes/0/capability, This property is required at /exposes/0/source, This property is required at /exposes/0/target_path")),
         },
         test_cm_exposes_bad_type => {
             input = json!({
                 "exposes": [
                     {
-                        "type": "bad",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "bad": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -463,7 +482,7 @@ mod tests {
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /exposes/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "OneOf conditions are not met at /exposes/0/capability")),
         },
 
         // offers
@@ -471,8 +490,11 @@ mod tests {
             input = json!({
                 "offers": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.logger.LogSink",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.logger.LogSink"
+                            }
+                        },
                         "source": {
                             "realm": {}
                         },
@@ -484,8 +506,11 @@ mod tests {
                         ]
                     },
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -501,8 +526,11 @@ mod tests {
                         ]
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/data/assets",
+                        "capability": {
+                            "directory": {
+                               "path": "/data/assets"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "cat_provider"
@@ -523,8 +551,11 @@ mod tests {
             input = json!({
                 "offers": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.logger.LogSink",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.logger.LogSink"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "abcdefghijklmnopqrstuvwxyz0123456789_-."
@@ -545,14 +576,17 @@ mod tests {
             input = json!({
                 "offers": [ {} ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /offers/0/source, This property is required at /offers/0/source_path, This property is required at /offers/0/targets, This property is required at /offers/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "This property is required at /offers/0/capability, This property is required at /offers/0/source, This property is required at /offers/0/targets")),
         },
         test_cm_offers_bad_type => {
             input = json!({
                 "offers": [
                     {
-                        "type": "bad",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "bad": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -565,14 +599,17 @@ mod tests {
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /offers/0/type")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "OneOf conditions are not met at /offers/0/capability")),
         },
         test_cm_offers_target_missing_props => {
             input = json!({
                 "offers": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "cat_viewer"
@@ -588,8 +625,11 @@ mod tests {
             input = json!({
                 "offers": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -667,8 +707,11 @@ mod tests {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": "/foo/?!@#$%/Bar",
+                        "capability": {
+                            "directory": {
+                               "path": "/foo/?!@#$%/Bar"
+                            }
+                        },
                         "target_path": "/bar/&*()/Baz"
                     }
                 ]
@@ -679,61 +722,76 @@ mod tests {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": "",
+                        "capability": {
+                            "directory": {
+                                "path": ""
+                            }
+                        },
                         "target_path": "/bar"
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "MinLength condition is not met at /uses/0/source_path, Pattern condition is not met at /uses/0/source_path")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "MinLength condition is not met at /uses/0/capability/directory/path, Pattern condition is not met at /uses/0/capability/directory/path")),
         },
         test_cm_path_invalid_root => {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": "/",
+                        "capability": {
+                            "directory": {
+                               "path": "/"
+                            }
+                        },
                         "target_path": "/bar"
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/source_path")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/capability/directory/path")),
         },
         test_cm_path_invalid_relative => {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": "foo/bar",
+                        "capability": {
+                            "directory": {
+                               "path": "foo/bar"
+                            }
+                        },
                         "target_path": "/bar"
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/source_path")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/capability/directory/path")),
         },
         test_cm_path_invalid_trailing => {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": "/foo/bar/",
+                        "capability": {
+                            "directory": {
+                               "path": "/foo/bar/"
+                            }
+                        },
                         "target_path": "/bar"
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/source_path")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "Pattern condition is not met at /uses/0/capability/directory/path")),
         },
         test_cm_path_too_long => {
             input = json!({
                 "uses": [
                     {
-                        "type": "directory",
-                        "source_path": format!("/{}", "a".repeat(1024)),
+                        "capability": {
+                            "directory": {
+                                "path": format!("/{}", "a".repeat(1024))
+                            }
+                        },
                         "target_path": "/bar"
                     }
                 ]
             }),
-            result = Err(Error::validate_schema(CM_SCHEMA, "MaxLength condition is not met at /uses/0/source_path")),
+            result = Err(Error::validate_schema(CM_SCHEMA, "MaxLength condition is not met at /uses/0/capability/directory/path")),
         },
         test_cm_name => {
             input = json!({
@@ -811,8 +869,11 @@ mod tests {
             input = json!({
                 "exposes": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {},
                         "target_path": "/svc/fuchsia.ui.Scenic"
                     }
@@ -824,8 +885,11 @@ mod tests {
             input = json!({
                 "exposes": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "realm": {},
                             "myself": {}
@@ -840,8 +904,11 @@ mod tests {
             input = json!({
                 "exposes": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.ui.Scenic",
+                        "capability": {
+                            "service": {
+                               "path": "/svc/fuchsia.ui.Scenic"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "bad^"
diff --git a/garnet/bin/cmc/tests/golden_debug.cm b/garnet/bin/cmc/tests/golden_debug.cm
index 0909cb5e683f36860eb27a5dbd384e445c1c578b..526d761128f0c73ab9f37d1efddf67f7ccea9338 100644
--- a/garnet/bin/cmc/tests/golden_debug.cm
+++ b/garnet/bin/cmc/tests/golden_debug.cm
@@ -4,15 +4,21 @@
     },
     "uses": [
         {
-            "type": "service",
-            "source_path": "/fonts/CoolFonts",
+            "capability": {
+                "service": {
+                    "path": "/fonts/CoolFonts"
+                }
+            },
             "target_path": "/svc/fuchsia.fonts.Provider"
         }
     ],
     "exposes": [
         {
-            "type": "directory",
-            "source_path": "/volumes/blobfs",
+            "capability": {
+                "directory": {
+                    "path": "/volumes/blobfs"
+                }
+            },
             "source": {
                 "myself": {}
             },
@@ -21,8 +27,11 @@
     ],
     "offers": [
         {
-            "type": "service",
-            "source_path": "/svc/fuchsia.logger.Log",
+            "capability": {
+                "service": {
+                    "path": "/svc/fuchsia.logger.Log"
+                }
+            },
             "source": {
                 "child": {
                     "name": "logger"
diff --git a/garnet/bin/cmc/tests/golden_release.cm b/garnet/bin/cmc/tests/golden_release.cm
index 81821eecc4034c30eb45093172fafe119b7b7578..3ca432834e093756fe59d5bebf304ef746a9b8e8 100644
--- a/garnet/bin/cmc/tests/golden_release.cm
+++ b/garnet/bin/cmc/tests/golden_release.cm
@@ -1 +1 @@
-{"program":{"binary":"bin/example"},"uses":[{"type":"service","source_path":"/fonts/CoolFonts","target_path":"/svc/fuchsia.fonts.Provider"}],"exposes":[{"type":"directory","source_path":"/volumes/blobfs","source":{"myself":{}},"target_path":"/volumes/blobfs"}],"offers":[{"type":"service","source_path":"/svc/fuchsia.logger.Log","source":{"child":{"name":"logger"}},"targets":[{"target_path":"/svc/fuchsia.logger.Log","child_name":"netstack"}]}],"children":[{"name":"logger","uri":"fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm","startup":"lazy"},{"name":"netstack","uri":"fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm","startup":"lazy"}],"facets":{"author":"Fuchsia","year":2018}}
\ No newline at end of file
+{"program":{"binary":"bin/example"},"uses":[{"capability":{"service":{"path":"/fonts/CoolFonts"}},"target_path":"/svc/fuchsia.fonts.Provider"}],"exposes":[{"capability":{"directory":{"path":"/volumes/blobfs"}},"source":{"myself":{}},"target_path":"/volumes/blobfs"}],"offers":[{"capability":{"service":{"path":"/svc/fuchsia.logger.Log"}},"source":{"child":{"name":"logger"}},"targets":[{"target_path":"/svc/fuchsia.logger.Log","child_name":"netstack"}]}],"children":[{"name":"logger","uri":"fuchsia-pkg://fuchsia.com/logger/stable#meta/logger.cm","startup":"lazy"},{"name":"netstack","uri":"fuchsia-pkg://fuchsia.com/netstack/stable#meta/netstack.cm","startup":"lazy"}],"facets":{"author":"Fuchsia","year":2018}}
\ No newline at end of file
diff --git a/garnet/bin/cmc/tests/integration_test.rs b/garnet/bin/cmc/tests/integration_test.rs
index 6d6435c330d7ec43cf769505abdae093e0392479..3862a4ff4bcb0fb12291a2f8d88437ba8e04e456 100644
--- a/garnet/bin/cmc/tests/integration_test.rs
+++ b/garnet/bin/cmc/tests/integration_test.rs
@@ -2,8 +2,8 @@ use cm_fidl_translator;
 use failure::Error;
 use fidl_fuchsia_data as fd;
 use fidl_fuchsia_sys2::{
-    CapabilityType, ChildDecl, ChildId, ComponentDecl, ExposeDecl, OfferDecl, OfferTarget,
-    RelativeId, SelfId, StartupMode, UseDecl,
+    Capability, ChildDecl, ChildId, ComponentDecl, DirectoryCapability, ExposeDecl, OfferDecl,
+    OfferTarget, RelativeId, SelfId, ServiceCapability, StartupMode, UseDecl,
 };
 use std::fs::File;
 use std::io::Read;
@@ -23,19 +23,22 @@ fn main() {
             }],
         };
         let uses = vec![UseDecl {
-            type_: Some(CapabilityType::Service),
-            source_path: Some("/fonts/CoolFonts".to_string()),
+            capability: Some(Capability::Service(ServiceCapability {
+                path: Some("/fonts/CoolFonts".to_string()),
+            })),
             target_path: Some("/svc/fuchsia.fonts.Provider".to_string()),
         }];
         let exposes = vec![ExposeDecl {
-            type_: Some(CapabilityType::Directory),
-            source_path: Some("/volumes/blobfs".to_string()),
-            source: Some(RelativeId::Myself(SelfId { dummy: None })),
+            capability: Some(Capability::Directory(DirectoryCapability {
+                path: Some("/volumes/blobfs".to_string()),
+            })),
+            source: Some(RelativeId::Myself(SelfId {})),
             target_path: Some("/volumes/blobfs".to_string()),
         }];
         let offers = vec![OfferDecl {
-            type_: Some(CapabilityType::Service),
-            source_path: Some("/svc/fuchsia.logger.Log".to_string()),
+            capability: Some(Capability::Service(ServiceCapability {
+                path: Some("/svc/fuchsia.logger.Log".to_string()),
+            })),
             source: Some(RelativeId::Child(ChildId { name: Some("logger".to_string()) })),
             targets: Some(vec![OfferTarget {
                 target_path: Some("/svc/fuchsia.logger.Log".to_string()),
diff --git a/garnet/bin/sys/component_manager/src/model/model.rs b/garnet/bin/sys/component_manager/src/model/model.rs
index 169fd6b0b144638c35776c4dce3a07b1ecc894d6..30064c4e1dbfc9a3bb34c2a0b074ee26b9829557 100644
--- a/garnet/bin/sys/component_manager/src/model/model.rs
+++ b/garnet/bin/sys/component_manager/src/model/model.rs
@@ -81,12 +81,12 @@ impl Model {
 
     /// Given a realm and path, lazily bind to the instance in the realm, open, then bind its eager
     /// children.
-    pub async fn bind_instance_and_open(
-        &self,
+    pub async fn bind_instance_and_open<'a>(
+        &'a self,
         realm: Arc<Mutex<Realm>>,
         flags: u32,
         open_mode: u32,
-        path: CapabilityPath,
+        path: &'a CapabilityPath,
         server_chan: zx::Channel,
     ) -> Result<(), ModelError> {
         let eager_children = {
diff --git a/garnet/bin/sys/component_manager/src/model/namespace.rs b/garnet/bin/sys/component_manager/src/model/namespace.rs
index 8b506c169a8b9e8082269fd25357725a60078ed6..18e50f3bcae8dd6fe7893c9e0f6d812ccc7e4978 100644
--- a/garnet/bin/sys/component_manager/src/model/namespace.rs
+++ b/garnet/bin/sys/component_manager/src/model/namespace.rs
@@ -75,8 +75,8 @@ impl IncomingNamespace {
         let mut directory_waiters = Vec::new();
 
         for use_ in &decl.uses {
-            match use_.type_ {
-                fsys::CapabilityType::Directory => {
+            match use_.capability {
+                cm_rust::Capability::Directory(_) => {
                     Self::add_directory_use(
                         &mut ns,
                         &mut directory_waiters,
@@ -85,7 +85,7 @@ impl IncomingNamespace {
                         abs_moniker.clone(),
                     )?;
                 }
-                fsys::CapabilityType::Service => {
+                cm_rust::Capability::Service(_) => {
                     Self::add_service_use(
                         &mut svc_dirs,
                         &use_,
@@ -120,9 +120,9 @@ impl IncomingNamespace {
         Ok(())
     }
 
-    /// add_directory_use will install one end of a channel pair in the namespace under the
-    /// target_path, and will add a future to waiters that will wait on the other end of a channel
-    /// for a signal. Once the channel is readable, the future calls `route_directory` and
+    /// Adds a directory waiter to `waiters` and updates `ns` to contain a handle for the
+    /// directory described by `use_`. Once the channel is readable, the future calls
+    /// `route_directory` to forward the channel to the source component's outgoing directory and
     /// terminates.
     fn add_directory_use(
         ns: &mut fsys::ComponentNamespace,
@@ -133,7 +133,7 @@ impl IncomingNamespace {
     ) -> Result<(), ModelError> {
         let (client_end, server_end) =
             create_endpoints().expect("could not create directory proxy endpoints");
-        let source_path = use_.source_path.clone();
+        let capability = use_.capability.clone();
         let route_on_usage = async move {
             // Wait for the channel to become readable.
             let server_end_chan = fasync::Channel::from_channel(server_end.into_channel())
@@ -144,7 +144,7 @@ impl IncomingNamespace {
             // Route this capability to the right component
             let res = await!(route_directory(
                 &model,
-                source_path.clone(),
+                &capability,
                 abs_moniker,
                 server_end_chan.into_zx_channel()
             ));
@@ -183,25 +183,24 @@ impl IncomingNamespace {
         Ok(())
     }
 
-    /// add_service_use will open the parent directory of source_path in componentmgr's namespace,
-    /// create a DirectoryBroker to proxy requests from target_path, and add the broker under a
-    /// pseudo directory in svc_dirs, creating a new pseudo directory if necessary.
+    /// Adds a service broker in `svc_dirs` for service described by `use_`. The service will be
+    /// proxied to the outgoing directory of the source component.
     fn add_service_use(
         svc_dirs: &mut HashMap<String, fvfs::directory::simple::Simple>,
         use_: &UseDecl,
         model: Model,
         abs_moniker: AbsoluteMoniker,
     ) -> Result<(), ModelError> {
-        let source_path = use_.source_path.clone();
+        let capability = use_.capability.clone();
         let route_service_fn = Box::new(move |server_end: ServerEnd<NodeMarker>| {
-            let source_path = source_path.clone();
+            let capability = capability.clone();
             let model = model.clone();
             let abs_moniker = abs_moniker.clone();
             fasync::spawn(
                 async move {
                     let res = await!(route_service(
                         &model,
-                        source_path,
+                        &capability,
                         abs_moniker,
                         server_end.into_channel()
                     ));
diff --git a/garnet/bin/sys/component_manager/src/model/routing.rs b/garnet/bin/sys/component_manager/src/model/routing.rs
index 77b2554a82db5c43d2a447bbe24e0eb10b3d2162..2904fd3d0d90e7c47ff2dc783cc5116cf6e3821c 100644
--- a/garnet/bin/sys/component_manager/src/model/routing.rs
+++ b/garnet/bin/sys/component_manager/src/model/routing.rs
@@ -5,10 +5,10 @@
 use {
     crate::io_util,
     crate::model::*,
-    cm_rust::{self, CapabilityPath, RelativeId},
+    cm_rust::{self, Capability, RelativeId},
     failure::format_err,
     fidl_fuchsia_io::{MODE_TYPE_DIRECTORY, MODE_TYPE_SERVICE, OPEN_RIGHT_READABLE},
-    fidl_fuchsia_sys2 as fsys, fuchsia_zircon as zx,
+    fuchsia_zircon as zx,
     futures::lock::Mutex,
     std::sync::Arc,
 };
@@ -16,79 +16,63 @@ use {
 /// Describes the source of a capability, as determined by `find_capability_source`
 #[derive(Debug)]
 enum CapabilitySource {
-    /// This capability source comes from the component described by this AbsoluteMoniker at
-    /// this path. The Realm is provided as well, as it has already been looked up by this
+    /// This capability originates from the component instance for the given Realm.
     /// point.
-    Component(CapabilityPath, Arc<Mutex<Realm>>),
-    /// This capability source comes from component manager's namespace, at this path
-    ComponentMgrNamespace(CapabilityPath),
+    Component(Capability, Arc<Mutex<Realm>>),
+    /// This capability originates from component manager's namespace.
+    ComponentMgrNamespace(Capability),
 }
 
 /// `route_directory` will find the source of the directory capability used at `source_path` by
 /// `absolute_moniker`, and pass along the `server_chan` to the hosting component's out
 /// directory (or componentmgr's namespace, if applicable)
-pub async fn route_directory(
-    model: &Model,
-    source_path: CapabilityPath,
+pub async fn route_directory<'a>(
+    model: &'a Model,
+    capability: &'a Capability,
     abs_moniker: AbsoluteMoniker,
     server_chan: zx::Channel,
 ) -> Result<(), ModelError> {
-    await!(route_capability(
-        model,
-        fsys::CapabilityType::Directory,
-        MODE_TYPE_DIRECTORY,
-        source_path,
-        abs_moniker,
-        server_chan
-    ))
+    await!(route_capability(model, MODE_TYPE_DIRECTORY, capability, abs_moniker, server_chan))
 }
 
 /// `route_service` will find the source of the service capability used at `source_path` by
 /// `absolute_moniker`, and pass along the `server_chan` to the hosting component's out
 /// directory (or componentmgr's namespace, if applicable)
-pub async fn route_service(
-    model: &Model,
-    source_path: CapabilityPath,
+pub async fn route_service<'a>(
+    model: &'a Model,
+    capability: &'a Capability,
     abs_moniker: AbsoluteMoniker,
     server_chan: zx::Channel,
 ) -> Result<(), ModelError> {
-    await!(route_capability(
-        model,
-        fsys::CapabilityType::Service,
-        MODE_TYPE_SERVICE,
-        source_path,
-        abs_moniker,
-        server_chan
-    ))
+    await!(route_capability(model, MODE_TYPE_SERVICE, capability, abs_moniker, server_chan))
 }
 
 /// `route_capability` will find the source of the capability `type_` used at `source_path` by
 /// `absolute_moniker`, and pass along the `server_chan` to the hosting component's out
 /// directory (or componentmgr's namespace, if applicable) using an open request with
 /// `open_mode`.
-async fn route_capability(
-    model: &Model,
-    type_: fsys::CapabilityType,
+async fn route_capability<'a>(
+    model: &'a Model,
     open_mode: u32,
-    source_path: CapabilityPath,
+    capability: &'a Capability,
     abs_moniker: AbsoluteMoniker,
     server_chan: zx::Channel,
 ) -> Result<(), ModelError> {
-    let source = await!(find_capability_source(model, type_, source_path, abs_moniker))?;
+    let source = await!(find_capability_source(model, capability, abs_moniker))?;
 
     let flags = OPEN_RIGHT_READABLE;
     match source {
-        CapabilitySource::ComponentMgrNamespace(path) => {
-            io_util::connect_in_namespace(&path.to_string(), server_chan)
+        CapabilitySource::ComponentMgrNamespace(source_capability) => {
+            io_util::connect_in_namespace(&source_capability.path().to_string(), server_chan)
                 .map_err(|e| ModelError::capability_discovery_error(e))?
         }
-        CapabilitySource::Component(path, realm) => {
+        CapabilitySource::Component(source_capability, realm) => {
             await!(Model::bind_instance_and_open(
                 &model,
                 realm,
                 flags,
                 open_mode,
-                path,
+                source_capability.path(),
                 server_chan
             ))?;
         }
@@ -98,20 +82,19 @@ async fn route_capability(
 }
 
 /// find_capability_source will walk the component tree to find the originating source of a
-/// capability, starting on the given abs_moniker and source_path. It returns the absolute
-/// moniker of the originating component, a reference to its realm, and the path that the
-/// component is exposing the capability from. If the absolute moniker and realm are None, then
-/// the capability originates at the returned path in componentmgr's namespace.
-async fn find_capability_source(
-    model: &Model,
-    type_: fsys::CapabilityType,
-    source_path: CapabilityPath,
+/// capability, starting on the given abs_moniker. It returns the absolute moniker of the
+/// originating component, a reference to its realm, and the capability exposed or offered at the
+/// originating source. If the absolute moniker and realm are None, then the capability originates
+/// at the returned path in componentmgr's namespace.
+async fn find_capability_source<'a>(
+    model: &'a Model,
+    used_capability: &'a Capability,
     abs_moniker: AbsoluteMoniker,
 ) -> Result<CapabilitySource, ModelError> {
     // Holds mutable state as we walk the tree
     struct State {
-        // The current path of the capability
-        path: CapabilityPath,
+        // The capability as it's represented in the current component
+        capability: Capability,
         // The name of the child we came from
         name: Option<ChildMoniker>,
         // The moniker of the component we are currently looking at
@@ -119,10 +102,10 @@ async fn find_capability_source(
     }
     let moniker = match abs_moniker.parent() {
         Some(m) => m,
-        None => return Ok(CapabilitySource::ComponentMgrNamespace(source_path)),
+        None => return Ok(CapabilitySource::ComponentMgrNamespace(used_capability.clone())),
     };
     let mut s = State {
-        path: source_path,
+        capability: used_capability.clone(),
         name: abs_moniker.path().last().map(|c| c.clone()),
         moniker: moniker,
     };
@@ -133,16 +116,20 @@ async fn find_capability_source(
         // This unwrap is safe because look_up_realm populates this field
         let decl = current_realm.instance.decl.as_ref().expect("missing offer decl");
 
-        if let Some(offer) = decl.find_offer_source(&s.path, &type_, &s.name.unwrap().name()) {
+        if let Some(offer) = decl.find_offer_source(&s.capability, &s.name.unwrap().name()) {
             match &offer.source {
                 RelativeId::Realm => {
                     // The offered capability comes from the realm, so follow the
                     // parent
-                    s.path = offer.source_path.clone();
+                    s.capability = offer.capability.clone();
                     s.name = s.moniker.path().last().map(|c| c.clone());
                     s.moniker = match s.moniker.parent() {
                         Some(m) => m,
-                        None => return Ok(CapabilitySource::ComponentMgrNamespace(s.path)),
+                        None => {
+                            return Ok(CapabilitySource::ComponentMgrNamespace(
+                                s.capability.clone(),
+                            ))
+                        }
                     };
                     continue 'offerloop;
                 }
@@ -150,14 +137,14 @@ async fn find_capability_source(
                     // The offered capability comes from the current component,
                     // return our current location in the tree.
                     return Ok(CapabilitySource::Component(
-                        offer.source_path.clone(),
+                        offer.capability.clone(),
                         current_realm_mutex.clone(),
                     ));
                 }
                 RelativeId::Child(child_name) => {
                     // The offered capability comes from a child, break the loop
                     // and begin walking the expose chain.
-                    s.path = offer.source_path.clone();
+                    s.capability = offer.capability.clone();
                     s.moniker = s.moniker.child(ChildMoniker::new(child_name.to_string()));
                     break 'offerloop;
                 }
@@ -165,7 +152,7 @@ async fn find_capability_source(
         } else {
             return Err(ModelError::capability_discovery_error(format_err!(
                 "no matching offers found for capability {} from component {}",
-                s.path,
+                s.capability,
                 s.moniker
             )));
         }
@@ -177,19 +164,19 @@ async fn find_capability_source(
         // This unwrap is safe because look_up_realm populates this field
         let decl = current_realm.instance.decl.as_ref().expect("missing expose decl");
 
-        if let Some(expose) = decl.find_expose_source(&s.path, &type_) {
+        if let Some(expose) = decl.find_expose_source(&s.capability) {
             match &expose.source {
                 RelativeId::Myself => {
                     // The offered capability comes from the current component, return our
                     // current location in the tree.
                     return Ok(CapabilitySource::Component(
-                        expose.source_path.clone(),
+                        expose.capability.clone(),
                         current_realm_mutex.clone(),
                     ));
                 }
                 RelativeId::Child(child_name) => {
                     // The offered capability comes from a child, so follow the child.
-                    s.path = expose.source_path.clone();
+                    s.capability = expose.capability.clone();
                     s.moniker = s.moniker.child(ChildMoniker::new(child_name.to_string()));
                     continue;
                 }
@@ -199,7 +186,7 @@ async fn find_capability_source(
             // We didn't find any matching exposes! Oh no!
             return Err(ModelError::capability_discovery_error(format_err!(
                 "no matching exposes found for capability {} from component {}",
-                s.path,
+                s.capability,
                 s.moniker
             )));
         }
diff --git a/garnet/bin/sys/component_manager/src/model/tests/routing.rs b/garnet/bin/sys/component_manager/src/model/tests/routing.rs
index f026fb2ada86cc9350666d8992aa39cdccf5ee02..5be37439c9bd8cc7d86ca78c4879713116038749 100644
--- a/garnet/bin/sys/component_manager/src/model/tests/routing.rs
+++ b/garnet/bin/sys/component_manager/src/model/tests/routing.rs
@@ -6,8 +6,8 @@ use {
     crate::model::tests::routing_test_helpers::*,
     crate::model::*,
     cm_rust::{
-        self, CapabilityPath, ChildDecl, ComponentDecl, ExposeDecl, OfferDecl, OfferTarget,
-        RelativeId, UseDecl,
+        self, Capability, CapabilityPath, ChildDecl, ComponentDecl, ExposeDecl, OfferDecl,
+        OfferTarget, RelativeId, UseDecl,
     },
     fidl_fuchsia_sys2 as fsys,
     std::convert::TryFrom,
@@ -26,8 +26,8 @@ async fn use_from_parent() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["b"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["b"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -35,8 +35,9 @@ async fn use_from_parent() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/bar").unwrap(),
@@ -44,8 +45,9 @@ async fn use_from_parent() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/bar").unwrap(),
@@ -66,13 +68,15 @@ async fn use_from_parent() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/bar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/bar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/bar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/bar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -100,8 +104,8 @@ async fn use_from_grandparent() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -109,8 +113,9 @@ async fn use_from_grandparent() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/bar").unwrap(),
@@ -118,8 +123,9 @@ async fn use_from_grandparent() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/bar").unwrap(),
@@ -140,8 +146,9 @@ async fn use_from_grandparent() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/bar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/bar").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/baz").unwrap(),
@@ -149,8 +156,9 @@ async fn use_from_grandparent() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/bar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/bar").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/baz").unwrap(),
@@ -171,13 +179,15 @@ async fn use_from_grandparent() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/baz").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/baz").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/baz").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/baz").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -202,8 +212,8 @@ async fn use_from_sibling_no_root() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -222,8 +232,9 @@ async fn use_from_sibling_no_root() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/bar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("d".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/foobar").unwrap(),
@@ -231,8 +242,9 @@ async fn use_from_sibling_no_root() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/bar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("d".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/foobar").unwrap(),
@@ -260,13 +272,15 @@ async fn use_from_sibling_no_root() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foobar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foobar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foobar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foobar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -278,14 +292,16 @@ async fn use_from_sibling_no_root() {
                 ComponentDecl {
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/data/bar").unwrap(),
                         },
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/svc/bar").unwrap(),
                         }
@@ -309,8 +325,8 @@ async fn use_from_sibling_root() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["c"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["c"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -318,8 +334,9 @@ async fn use_from_sibling_root() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/bar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/baz").unwrap(),
@@ -327,8 +344,9 @@ async fn use_from_sibling_root() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/bar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/baz").unwrap(),
@@ -356,14 +374,16 @@ async fn use_from_sibling_root() {
                 ComponentDecl {
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/data/bar").unwrap(),
                         },
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/svc/bar").unwrap(),
                         },
@@ -376,13 +396,15 @@ async fn use_from_sibling_root() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/baz").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/baz").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/baz").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/baz").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -408,8 +430,8 @@ async fn use_from_niece() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["c"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["c"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -417,8 +439,9 @@ async fn use_from_niece() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/baz").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/baz").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/foobar").unwrap(),
@@ -426,8 +449,9 @@ async fn use_from_niece() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/baz").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/baz").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/foobar").unwrap(),
@@ -455,14 +479,16 @@ async fn use_from_niece() {
                 ComponentDecl {
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/bar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("d".to_string()),
                             target_path: CapabilityPath::try_from("/data/baz").unwrap(),
                         },
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/bar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/bar").unwrap(),
+                            ),
                             source: RelativeId::Child("d".to_string()),
                             target_path: CapabilityPath::try_from("/svc/baz").unwrap(),
                         },
@@ -480,13 +506,15 @@ async fn use_from_niece() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foobar").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foobar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foobar").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foobar").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -498,14 +526,16 @@ async fn use_from_niece() {
                 ComponentDecl {
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/data/bar").unwrap(),
                         },
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/svc/bar").unwrap(),
                         }
@@ -534,10 +564,10 @@ async fn use_kitchen_sink() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b", "e"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["b", "e"]), fsys::CapabilityType::Service, true),
-            (AbsoluteMoniker::new(vec!["c", "f"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["c", "f"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["b", "e"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["b", "e"]), new_service_capability(), true),
+            (AbsoluteMoniker::new(vec!["c", "f"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["c", "f"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -545,8 +575,9 @@ async fn use_kitchen_sink() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
@@ -554,8 +585,9 @@ async fn use_kitchen_sink() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
@@ -584,8 +616,9 @@ async fn use_kitchen_sink() {
                     program: None,
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            ),
                             source: RelativeId::Child("d".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
@@ -593,8 +626,9 @@ async fn use_kitchen_sink() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
@@ -603,8 +637,9 @@ async fn use_kitchen_sink() {
                         },
                     ],
                     exposes: vec![ExposeDecl {
-                        type_: fsys::CapabilityType::Directory,
-                        source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                        capability: Capability::Directory(
+                            CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                        ),
                         source: RelativeId::Child("d".to_string()),
                         target_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
                     },],
@@ -629,8 +664,9 @@ async fn use_kitchen_sink() {
                     program: None,
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
@@ -638,8 +674,9 @@ async fn use_kitchen_sink() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                            ),
                             source: RelativeId::Child("g".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
@@ -666,8 +703,9 @@ async fn use_kitchen_sink() {
                 "d",
                 ComponentDecl {
                     exposes: vec![ExposeDecl {
-                        type_: fsys::CapabilityType::Directory,
-                        source_path: CapabilityPath::try_from("/data/foo").unwrap(),
+                        capability: Capability::Directory(
+                            CapabilityPath::try_from("/data/foo").unwrap(),
+                        ),
                         source: RelativeId::Myself,
                         target_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
                     },],
@@ -679,13 +717,15 @@ async fn use_kitchen_sink() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo_from_a").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -697,13 +737,15 @@ async fn use_kitchen_sink() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/foo_from_d").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -715,8 +757,9 @@ async fn use_kitchen_sink() {
                 ComponentDecl {
                     program: None,
                     exposes: vec![ExposeDecl {
-                        type_: fsys::CapabilityType::Service,
-                        source_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                        capability: Capability::Service(
+                            CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
+                        ),
                         source: RelativeId::Child("h".to_string()),
                         target_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
                     },],
@@ -732,8 +775,9 @@ async fn use_kitchen_sink() {
                 "h",
                 ComponentDecl {
                     exposes: vec![ExposeDecl {
-                        type_: fsys::CapabilityType::Service,
-                        source_path: CapabilityPath::try_from("/svc/foo").unwrap(),
+                        capability: Capability::Service(
+                            CapabilityPath::try_from("/svc/foo").unwrap(),
+                        ),
                         source: RelativeId::Myself,
                         target_path: CapabilityPath::try_from("/svc/foo_from_h").unwrap(),
                     },],
@@ -760,8 +804,8 @@ async fn use_from_component_manager_namespace() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Directory, true),
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Service, true),
+            (AbsoluteMoniker::new(vec!["b"]), new_directory_capability(), true),
+            (AbsoluteMoniker::new(vec!["b"]), new_service_capability(), true),
         ],
         components: vec![
             (
@@ -769,8 +813,9 @@ async fn use_from_component_manager_namespace() {
                 ComponentDecl {
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/hippo/data/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/hippo/data/foo").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/foo").unwrap(),
@@ -778,9 +823,9 @@ async fn use_from_component_manager_namespace() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/fidl.examples.echo.Echo")
-                                .unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/fidl.examples.echo.Echo").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/echo/echo").unwrap(),
@@ -801,13 +846,15 @@ async fn use_from_component_manager_namespace() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/foo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/foo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/echo/echo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/echo/echo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -829,8 +876,8 @@ async fn use_not_offered() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Directory, false),
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Service, false),
+            (AbsoluteMoniker::new(vec!["b"]), new_directory_capability(), false),
+            (AbsoluteMoniker::new(vec!["b"]), new_service_capability(), false),
         ],
         components: vec![
             (
@@ -850,13 +897,15 @@ async fn use_not_offered() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -880,8 +929,8 @@ async fn use_offer_source_not_exposed() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Directory, false),
-            (AbsoluteMoniker::new(vec!["c"]), fsys::CapabilityType::Service, false),
+            (AbsoluteMoniker::new(vec!["c"]), new_directory_capability(), false),
+            (AbsoluteMoniker::new(vec!["c"]), new_service_capability(), false),
         ],
         components: vec![
             (
@@ -890,8 +939,9 @@ async fn use_offer_source_not_exposed() {
                     program: None,
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
@@ -899,8 +949,9 @@ async fn use_offer_source_not_exposed() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             source: RelativeId::Child("b".to_string()),
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
@@ -929,13 +980,15 @@ async fn use_offer_source_not_exposed() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -961,8 +1014,8 @@ async fn use_offer_source_not_offered() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Directory, false),
-            (AbsoluteMoniker::new(vec!["b", "c"]), fsys::CapabilityType::Service, false),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_directory_capability(), false),
+            (AbsoluteMoniker::new(vec!["b", "c"]), new_service_capability(), false),
         ],
         components: vec![
             (
@@ -982,8 +1035,9 @@ async fn use_offer_source_not_offered() {
                     program: None,
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
@@ -991,8 +1045,9 @@ async fn use_offer_source_not_offered() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             source: RelativeId::Realm,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
@@ -1013,13 +1068,15 @@ async fn use_offer_source_not_offered() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -1045,8 +1102,8 @@ async fn use_from_expose() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Directory, false),
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Service, false),
+            (AbsoluteMoniker::new(vec!["b"]), new_directory_capability(), false),
+            (AbsoluteMoniker::new(vec!["b"]), new_service_capability(), false),
         ],
         components: vec![
             (
@@ -1066,13 +1123,15 @@ async fn use_from_expose() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
@@ -1089,14 +1148,16 @@ async fn use_from_expose() {
                 ComponentDecl {
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         }
@@ -1121,8 +1182,8 @@ async fn offer_from_non_executable() {
     await!(run_routing_test(TestInputs {
         root_component: "a",
         users_to_check: vec![
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Directory, false),
-            (AbsoluteMoniker::new(vec!["b"]), fsys::CapabilityType::Service, false),
+            (AbsoluteMoniker::new(vec!["b"]), new_directory_capability(), false),
+            (AbsoluteMoniker::new(vec!["b"]), new_service_capability(), false),
         ],
         components: vec![
             (
@@ -1131,8 +1192,9 @@ async fn offer_from_non_executable() {
                     program: None,
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
@@ -1140,8 +1202,9 @@ async fn offer_from_non_executable() {
                             }],
                         },
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             source: RelativeId::Myself,
                             targets: vec![OfferTarget {
                                 target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
@@ -1162,13 +1225,15 @@ async fn offer_from_non_executable() {
                 ComponentDecl {
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: CapabilityPath::try_from("/data/hippo").unwrap(),
+                            capability: Capability::Directory(
+                                CapabilityPath::try_from("/data/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/data/hippo").unwrap(),
                         },
                         UseDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            capability: Capability::Service(
+                                CapabilityPath::try_from("/svc/hippo").unwrap(),
+                            ),
                             target_path: CapabilityPath::try_from("/svc/hippo").unwrap(),
                         },
                     ],
diff --git a/garnet/bin/sys/component_manager/src/model/tests/routing_test_helpers.rs b/garnet/bin/sys/component_manager/src/model/tests/routing_test_helpers.rs
index 8395e7d94367591c2721beda2fae63043e437581..2191b14adbf49615188c8b2ed23f000f85dbf5d9 100644
--- a/garnet/bin/sys/component_manager/src/model/tests/routing_test_helpers.rs
+++ b/garnet/bin/sys/component_manager/src/model/tests/routing_test_helpers.rs
@@ -4,7 +4,7 @@
 
 use {
     crate::{directory_broker, io_util, model::tests::mocks::*, model::*},
-    cm_rust::{ComponentDecl, RelativeId, UseDecl},
+    cm_rust::{Capability, CapabilityPath, ComponentDecl, RelativeId, UseDecl},
     fidl::endpoints::{ClientEnd, ServerEnd},
     fidl_fidl_examples_echo::{self as echo, EchoMarker, EchoRequest, EchoRequestStream},
     fidl_fuchsia_data as fdata,
@@ -22,6 +22,7 @@ use {
     futures::TryStreamExt,
     std::{
         collections::{HashMap, HashSet},
+        convert::TryFrom,
         ffi::CString,
         iter,
         path::PathBuf,
@@ -152,16 +153,18 @@ fn echo_server_fn(server_end: ServerEnd<NodeMarker>) {
     );
 }
 
-/// Looks up `resolved_uri` in the namespace, and attempts to read /data/hippo/hippo. The file
+/// Looks up `resolved_uri` in the namespace, and attempts to read ${dir_path}/hippo. The file
 /// should contain the string "hippo".
-pub async fn read_data_hippo_hippo(
+pub async fn read_data(
+    path: CapabilityPath,
     resolved_uri: String,
     namespaces: Arc<Mutex<HashMap<String, fsys::ComponentNamespace>>>,
     should_succeed: bool,
 ) {
-    let dir_proxy = await!(get_dir("/data/hippo", resolved_uri, namespaces));
-    let path = PathBuf::from("hippo");
-    let file_proxy = io_util::open_file(&dir_proxy, &path).expect("failed to open file");
+    let path = path.to_string();
+    let dir_proxy = await!(get_dir(&path, resolved_uri, namespaces));
+    let file = PathBuf::from("hippo");
+    let file_proxy = io_util::open_file(&dir_proxy, &file).expect("failed to open file");
     let res = await!(io_util::read_file(&file_proxy));
 
     match should_succeed {
@@ -173,17 +176,18 @@ pub async fn read_data_hippo_hippo(
     }
 }
 
-/// Looks up `resolved_uri` in the namespace, and attempts to use /svc/hippo. Expects the service
+/// Looks up `resolved_uri` in the namespace, and attempts to use `path`. Expects the service
 /// to be fidl.examples.echo.Echo.
-async fn call_svc_hippo(
+async fn call_svc(
+    path: CapabilityPath,
     resolved_uri: String,
     namespaces: Arc<Mutex<HashMap<String, fsys::ComponentNamespace>>>,
     should_succeed: bool,
 ) {
-    let dir_proxy = await!(get_dir("/svc", resolved_uri, namespaces));
-    let path = PathBuf::from("hippo");
-    let node_proxy = io_util::open_node(&dir_proxy, &path, MODE_TYPE_SERVICE)
-        .expect("failed to open echo service");
+    let dir_proxy = await!(get_dir(&path.dirname, resolved_uri, namespaces));
+    let node_proxy =
+        io_util::open_node(&dir_proxy, &PathBuf::from(path.basename), MODE_TYPE_SERVICE)
+            .expect("failed to open echo service");
     let echo_proxy = echo::EchoProxy::new(node_proxy.into_channel().unwrap());
     let res = await!(echo_proxy.echo_string(Some("hippos")));
 
@@ -237,9 +241,9 @@ async fn check_namespace(
     let expected_paths_hs: HashSet<String> = decl
         .uses
         .into_iter()
-        .map(|UseDecl { type_, target_path, .. }| match type_ {
-            fsys::CapabilityType::Directory => target_path.to_string(),
-            fsys::CapabilityType::Service => target_path.dirname,
+        .map(|UseDecl { capability, target_path }| match capability {
+            Capability::Directory(_) => target_path.to_string(),
+            Capability::Service(_) => target_path.dirname,
         })
         .collect();
     let mut expected_paths = vec![];
@@ -263,14 +267,23 @@ async fn check_namespace(
 pub struct TestInputs<'a> {
     /// The name of the root component.
     pub root_component: &'a str,
-    /// The use decls on a component which should be checked. Service capabilities are assumed to
-    /// be installed at `/svc/hippo` and directory capabilities are assumed to be installed at
-    /// `/data/hippo`. The bool marks if this usage is expected to succeed or not.
-    pub users_to_check: Vec<(AbsoluteMoniker, fsys::CapabilityType, bool)>,
+    /// The use decls on a component which should be checked. The bool marks if this usage is
+    /// expected to succeed or not.
+    pub users_to_check: Vec<(AbsoluteMoniker, Capability, bool)>,
     /// The component declarations that comprise the component tree
     pub components: Vec<(&'a str, ComponentDecl)>,
 }
 
+/// Construct a capability for the hippo service.
+pub fn new_service_capability() -> Capability {
+    Capability::Service(CapabilityPath::try_from("/svc/hippo").unwrap())
+}
+
+/// Construct a capability for the hippo directory.
+pub fn new_directory_capability() -> Capability {
+    Capability::Directory(CapabilityPath::try_from("/data/hippo").unwrap())
+}
+
 /// construct the given component topology, host `/svc/foo` and `/data/foo` from the outgoing
 /// directory of any component offering or exposing from `Myself`, and attempt to use the use
 /// declarations referenced in `test.users_to_check`
@@ -285,16 +298,14 @@ pub async fn run_routing_test<'a>(test: TestInputs<'a>) {
         let source_iter = decl
             .offers
             .iter()
-            .map(|o| (o.type_.clone(), o.source.clone()))
-            .chain(decl.exposes.iter().map(|e| (e.type_.clone(), e.source.clone())));
+            .map(|o| (o.capability.clone(), o.source.clone()))
+            .chain(decl.exposes.iter().map(|e| (e.capability.clone(), e.source.clone())));
         let mut out_dir = None;
-        for (type_, source) in source_iter {
+        for (capability, source) in source_iter {
             if source == RelativeId::Myself {
-                match type_ {
-                    fsys::CapabilityType::Service => {
-                        out_dir.get_or_insert(OutDir::new()).add_service()
-                    }
-                    fsys::CapabilityType::Directory => {
+                match capability {
+                    Capability::Service(_) => out_dir.get_or_insert(OutDir::new()).add_service(),
+                    Capability::Directory(_) => {
                         out_dir.get_or_insert(OutDir::new()).add_directory()
                     }
                 }
@@ -312,21 +323,19 @@ pub async fn run_routing_test<'a>(test: TestInputs<'a>) {
         root_resolver_registry: resolver,
         root_default_runner: Box::new(runner),
     });
-    for (moniker, type_, should_succeed) in test.users_to_check {
+    for (moniker, capability, should_succeed) in test.users_to_check {
         assert!(await!(model.look_up_and_bind_instance(moniker.clone())).is_ok());
         let component_name =
             moniker.path().last().expect("didn't expect a root component").name().to_string();
         let component_resolved_url = format!("test:///{}_resolved", &component_name);
         await!(check_namespace(component_name, namespaces.clone(), test.components.clone()));
-        match type_ {
-            fsys::CapabilityType::Service => {
-                await!(call_svc_hippo(component_resolved_url, namespaces.clone(), should_succeed))
+        match capability {
+            Capability::Service(path) => {
+                await!(call_svc(path, component_resolved_url, namespaces.clone(), should_succeed))
+            }
+            Capability::Directory(path) => {
+                await!(read_data(path, component_resolved_url, namespaces.clone(), should_succeed))
             }
-            fsys::CapabilityType::Directory => await!(read_data_hippo_hippo(
-                component_resolved_url,
-                namespaces.clone(),
-                should_succeed
-            )),
         };
     }
 }
diff --git a/garnet/lib/rust/cm_fidl_translator/src/lib.rs b/garnet/lib/rust/cm_fidl_translator/src/lib.rs
index 81dde28e4a83ee132463e415126b878a892fa31d..d93b5b126d56f761096a02245b7a8a84b1ddac92 100644
--- a/garnet/lib/rust/cm_fidl_translator/src/lib.rs
+++ b/garnet/lib/rust/cm_fidl_translator/src/lib.rs
@@ -85,8 +85,7 @@ impl CmInto<fsys::ComponentDecl> for cm::Document {
 impl CmInto<fsys::UseDecl> for cm::Use {
     fn cm_into(self) -> Result<fsys::UseDecl, Error> {
         Ok(fsys::UseDecl {
-            type_: Some(capability_from_str(&self.r#type)?),
-            source_path: Some(self.source_path),
+            capability: Some(self.capability.cm_into()?),
             target_path: Some(self.target_path),
         })
     }
@@ -95,8 +94,7 @@ impl CmInto<fsys::UseDecl> for cm::Use {
 impl CmInto<fsys::ExposeDecl> for cm::Expose {
     fn cm_into(self) -> Result<fsys::ExposeDecl, Error> {
         Ok(fsys::ExposeDecl {
-            type_: Some(capability_from_str(&self.r#type)?),
-            source_path: Some(self.source_path),
+            capability: Some(self.capability.cm_into()?),
             source: Some(self.source.cm_into()?),
             target_path: Some(self.target_path),
         })
@@ -106,8 +104,7 @@ impl CmInto<fsys::ExposeDecl> for cm::Expose {
 impl CmInto<fsys::OfferDecl> for cm::Offer {
     fn cm_into(self) -> Result<fsys::OfferDecl, Error> {
         Ok(fsys::OfferDecl {
-            type_: Some(capability_from_str(&self.r#type)?),
-            source_path: Some(self.source_path),
+            capability: Some(self.capability.cm_into()?),
             source: Some(self.source.cm_into()?),
             targets: Some(self.targets.cm_into()?),
         })
@@ -124,38 +121,46 @@ impl CmInto<fsys::ChildDecl> for cm::Child {
     }
 }
 
+impl CmInto<fsys::Capability> for cm::Capability {
+    fn cm_into(self) -> Result<fsys::Capability, Error> {
+        Ok(match self {
+            cm::Capability::Service(s) => fsys::Capability::Service(s.cm_into()?),
+            cm::Capability::Directory(d) => fsys::Capability::Directory(d.cm_into()?),
+        })
+    }
+}
+
+impl CmInto<fsys::ServiceCapability> for cm::Service {
+    fn cm_into(self) -> Result<fsys::ServiceCapability, Error> {
+        Ok(fsys::ServiceCapability { path: Some(self.path) })
+    }
+}
+
+impl CmInto<fsys::DirectoryCapability> for cm::Directory {
+    fn cm_into(self) -> Result<fsys::DirectoryCapability, Error> {
+        Ok(fsys::DirectoryCapability { path: Some(self.path) })
+    }
+}
+
 impl CmInto<fsys::RelativeId> for cm::Source {
     fn cm_into(self) -> Result<fsys::RelativeId, Error> {
-        let num_set = self.realm.is_some() as i32
-            + self.myself.is_some() as i32
-            + self.child.is_some() as i32;
-        if num_set > 1 {
-            return Err(Error::parse(format!(
-                "More than one RelativeId variant is set: {:?}",
-                &self
-            )));
-        }
-        if let Some(realm) = self.realm {
-            Ok(fsys::RelativeId::Realm(realm.cm_into()?))
-        } else if let Some(myself) = self.myself {
-            Ok(fsys::RelativeId::Myself(myself.cm_into()?))
-        } else if let Some(child) = self.child {
-            Ok(fsys::RelativeId::Child(child.cm_into()?))
-        } else {
-            Err(Error::parse(format!("No RelativeId variant is set: {:?}", &self)))
-        }
+        Ok(match self {
+            cm::Source::Realm(r) => fsys::RelativeId::Realm(r.cm_into()?),
+            cm::Source::Myself(s) => fsys::RelativeId::Myself(s.cm_into()?),
+            cm::Source::Child(c) => fsys::RelativeId::Child(c.cm_into()?),
+        })
     }
 }
 
 impl CmInto<fsys::RealmId> for cm::RealmId {
     fn cm_into(self) -> Result<fsys::RealmId, Error> {
-        Ok(fsys::RealmId { dummy: None })
+        Ok(fsys::RealmId {})
     }
 }
 
 impl CmInto<fsys::SelfId> for cm::SelfId {
     fn cm_into(self) -> Result<fsys::SelfId, Error> {
-        Ok(fsys::SelfId { dummy: None })
+        Ok(fsys::SelfId {})
     }
 }
 
@@ -227,14 +232,6 @@ fn convert_value(v: Value) -> Result<Option<Box<fdata::Value>>, Error> {
     })
 }
 
-fn capability_from_str(value: &str) -> Result<fsys::CapabilityType, Error> {
-    match value {
-        cm::SERVICE => Ok(fsys::CapabilityType::Service),
-        cm::DIRECTORY => Ok(fsys::CapabilityType::Directory),
-        _ => Err(Error::parse(format!("Unknown capability type: {}", value))),
-    }
-}
-
 fn startup_from_str(value: &str) -> Result<fsys::StartupMode, Error> {
     match value {
         cm::LAZY => Ok(fsys::StartupMode::Lazy),
@@ -288,8 +285,7 @@ mod tests {
         let input = json!({
             "exposes": [
                 {
-                    "type": "nothing",
-                    "source_path": "/svc/fuchsia.logger.Log",
+                    "capability": {},
                     "source": {
                         "myself": {}
                     },
@@ -300,7 +296,7 @@ mod tests {
 
         let expected_res: Result<fsys::ComponentDecl, Error> = Err(Error::validate_schema(
             CM_SCHEMA,
-            "Pattern condition is not met at /exposes/0/type",
+            "OneOf conditions are not met at /exposes/0/capability",
         ));
         let res = translate(&format!("{}", input));
         assert_eq!(format!("{:?}", res), format!("{:?}", expected_res));
@@ -413,13 +409,19 @@ mod tests {
             input = json!({
                 "uses": [
                     {
-                        "type": "service",
-                        "source_path": "/fonts/CoolFonts",
+                        "capability": {
+                            "service": {
+                                "path": "/fonts/CoolFonts"
+                            }
+                        },
                         "target_path": "/svc/fuchsia.fonts.Provider"
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/data/assets",
+                        "capability": {
+                            "directory": {
+                                "path": "/data/assets"
+                            }
+                        },
                         "target_path": "/data/assets"
                     }
                 ]
@@ -427,13 +429,15 @@ mod tests {
             output = {
                 let uses = vec![
                     fsys::UseDecl{
-                        type_: Some(fsys::CapabilityType::Service),
-                        source_path: Some("/fonts/CoolFonts".to_string()),
+                        capability: Some(fsys::Capability::Service(fsys::ServiceCapability{
+                            path: Some("/fonts/CoolFonts".to_string()),
+                        })),
                         target_path: Some("/svc/fuchsia.fonts.Provider".to_string()),
                     },
                     fsys::UseDecl{
-                        type_: Some(fsys::CapabilityType::Directory),
-                        source_path: Some("/data/assets".to_string()),
+                        capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability{
+                            path: Some("/data/assets".to_string()),
+                        })),
                         target_path: Some("/data/assets".to_string()),
                     },
                 ];
@@ -446,8 +450,11 @@ mod tests {
             input = json!({
                 "exposes": [
                     {
-                        "type": "service",
-                        "source_path": "/loggers/fuchsia.logger.Log",
+                        "capability": {
+                            "service": {
+                                "path": "/loggers/fuchsia.logger.Log"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "logger"
@@ -456,8 +463,11 @@ mod tests {
                         "target_path": "/svc/fuchsia.logger.Log"
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/volumes/blobfs",
+                        "capability": {
+                            "directory": {
+                                "path": "/volumes/blobfs"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -475,17 +485,19 @@ mod tests {
             output = {
                 let exposes = vec![
                     fsys::ExposeDecl{
-                        type_: Some(fsys::CapabilityType::Service),
-                        source_path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        capability: Some(fsys::Capability::Service(fsys::ServiceCapability{
+                            path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        })),
                         source: Some(fsys::RelativeId::Child(fsys::ChildId {
                             name: Some("logger".to_string()),
                         })),
                         target_path: Some("/svc/fuchsia.logger.Log".to_string()),
                     },
                     fsys::ExposeDecl{
-                        type_: Some(fsys::CapabilityType::Directory),
-                        source_path: Some("/volumes/blobfs".to_string()),
-                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{dummy: None})),
+                        capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability{
+                            path: Some("/volumes/blobfs".to_string()),
+                        })),
+                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{})),
                         target_path: Some("/volumes/blobfs".to_string()),
                     },
                 ];
@@ -506,8 +518,11 @@ mod tests {
             input = json!({
                 "offers": [
                     {
-                        "type": "directory",
-                        "source_path": "/data/assets",
+                        "capability": {
+                            "directory": {
+                                "path": "/data/assets"
+                            }
+                        },
                         "source": {
                             "realm": {}
                         },
@@ -523,8 +538,11 @@ mod tests {
                         ]
                     },
                     {
-                        "type": "directory",
-                        "source_path": "/data/config",
+                        "capability": {
+                            "directory": {
+                                "path": "/data/config"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -536,8 +554,11 @@ mod tests {
                         ]
                     },
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.logger.Log",
+                        "capability": {
+                            "service": {
+                                "path": "/svc/fuchsia.logger.Log"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "logger"
@@ -567,9 +588,10 @@ mod tests {
             output = {
                 let offers = vec![
                     fsys::OfferDecl{
-                        type_: Some(fsys::CapabilityType::Directory),
-                        source_path: Some("/data/assets".to_string()),
-                        source: Some(fsys::RelativeId::Realm(fsys::RealmId{dummy: None})),
+                        capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability{
+                            path: Some("/data/assets".to_string()),
+                        })),
+                        source: Some(fsys::RelativeId::Realm(fsys::RealmId{})),
                         targets: Some(vec![
                             fsys::OfferTarget{
                                 target_path: Some("/data/realm_assets".to_string()),
@@ -582,9 +604,10 @@ mod tests {
                         ]),
                     },
                     fsys::OfferDecl{
-                        type_: Some(fsys::CapabilityType::Directory),
-                        source_path: Some("/data/config".to_string()),
-                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{dummy: None})),
+                        capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability{
+                            path: Some("/data/config".to_string()),
+                        })),
+                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{})),
                         targets: Some(vec![
                             fsys::OfferTarget{
                                 target_path: Some("/data/config".to_string()),
@@ -593,8 +616,9 @@ mod tests {
                         ]),
                     },
                     fsys::OfferDecl{
-                        type_: Some(fsys::CapabilityType::Service),
-                        source_path: Some("/svc/fuchsia.logger.Log".to_string()),
+                        capability: Some(fsys::Capability::Service(fsys::ServiceCapability{
+                            path: Some("/svc/fuchsia.logger.Log".to_string()),
+                        })),
                         source: Some(fsys::RelativeId::Child(fsys::ChildId {
                             name: Some("logger".to_string()),
                         })),
@@ -699,15 +723,21 @@ mod tests {
                 },
                 "uses": [
                     {
-                        "type": "service",
-                        "source_path": "/fonts/CoolFonts",
+                        "capability": {
+                            "service": {
+                                "path": "/fonts/CoolFonts"
+                            }
+                        },
                         "target_path": "/svc/fuchsia.fonts.Provider"
                     }
                 ],
                 "exposes": [
                     {
-                        "type": "directory",
-                        "source_path": "/volumes/blobfs",
+                        "capability": {
+                            "directory": {
+                                "path": "/volumes/blobfs"
+                            }
+                        },
                         "source": {
                             "myself": {}
                         },
@@ -716,8 +746,11 @@ mod tests {
                 ],
                 "offers": [
                     {
-                        "type": "service",
-                        "source_path": "/svc/fuchsia.logger.Log",
+                        "capability": {
+                            "service": {
+                                "path": "/svc/fuchsia.logger.Log"
+                            }
+                        },
                         "source": {
                             "child": {
                                 "name": "logger"
@@ -757,23 +790,26 @@ mod tests {
                 ]};
                 let uses = vec![
                     fsys::UseDecl{
-                        type_: Some(fsys::CapabilityType::Service),
-                        source_path: Some("/fonts/CoolFonts".to_string()),
+                        capability: Some(fsys::Capability::Service(fsys::ServiceCapability{
+                            path: Some("/fonts/CoolFonts".to_string()),
+                        })),
                         target_path: Some("/svc/fuchsia.fonts.Provider".to_string()),
                     },
                 ];
                 let exposes = vec![
                     fsys::ExposeDecl{
-                        type_: Some(fsys::CapabilityType::Directory),
-                        source_path: Some("/volumes/blobfs".to_string()),
-                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{dummy: None})),
+                        capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability{
+                            path: Some("/volumes/blobfs".to_string()),
+                        })),
+                        source: Some(fsys::RelativeId::Myself(fsys::SelfId{})),
                         target_path: Some("/volumes/blobfs".to_string()),
                     },
                 ];
                 let offers = vec![
                     fsys::OfferDecl{
-                        type_: Some(fsys::CapabilityType::Service),
-                        source_path: Some("/svc/fuchsia.logger.Log".to_string()),
+                        capability: Some(fsys::Capability::Service(fsys::ServiceCapability{
+                            path: Some("/svc/fuchsia.logger.Log".to_string()),
+                        })),
                         source: Some(fsys::RelativeId::Child(fsys::ChildId {
                             name: Some("logger".to_string()),
                         })),
diff --git a/garnet/lib/rust/cm_fidl_validator/src/lib.rs b/garnet/lib/rust/cm_fidl_validator/src/lib.rs
index 515f861c1e09119e1abc4711e3f48faefd84e7cd..69675dc6d33fca4800bcc854e47751aa0ae7d387 100644
--- a/garnet/lib/rust/cm_fidl_validator/src/lib.rs
+++ b/garnet/lib/rust/cm_fidl_validator/src/lib.rs
@@ -136,11 +136,7 @@ impl<'a> ValidationContext<'a> {
         // Validate "uses".
         if let Some(uses) = self.decl.uses.as_ref() {
             for use_ in uses.iter() {
-                if use_.type_.is_none() {
-                    self.errors.push(Error::missing_field("UseDecl", "type"));
-                }
-                PATH.check(use_.source_path.as_ref(), "UseDecl", "source_path", &mut self.errors);
-                PATH.check(use_.target_path.as_ref(), "UseDecl", "target_path", &mut self.errors);
+                self.validate_use_decl(&use_);
             }
         }
 
@@ -167,6 +163,30 @@ impl<'a> ValidationContext<'a> {
         }
     }
 
+    fn validate_use_decl(&mut self, use_: &fsys::UseDecl) {
+        self.validate_capability(use_.capability.as_ref(), "UseDecl");
+        PATH.check(use_.target_path.as_ref(), "UseDecl", "target_path", &mut self.errors);
+    }
+
+    fn validate_capability(&mut self, capability: Option<&fsys::Capability>, decl_type: &str) {
+        match capability.as_ref() {
+            Some(c) => match c {
+                fsys::Capability::Service(s) => {
+                    PATH.check(s.path.as_ref(), decl_type, "capability.path", &mut self.errors);
+                }
+                fsys::Capability::Directory(s) => {
+                    PATH.check(s.path.as_ref(), decl_type, "capability.path", &mut self.errors);
+                }
+                fsys::Capability::__UnknownVariant { .. } => {
+                    self.errors.push(Error::invalid_field(decl_type, "capability"));
+                }
+            },
+            None => {
+                self.errors.push(Error::missing_field(decl_type, "capability"));
+            }
+        }
+    }
+
     fn validate_child_decl(&mut self, child: &'a fsys::ChildDecl) {
         let name = child.name.as_ref();
         if NAME.check(name, "ChildDecl", "name", &mut self.errors) {
@@ -201,10 +221,7 @@ impl<'a> ValidationContext<'a> {
         expose: &'a fsys::ExposeDecl,
         prev_target_paths: &mut HashSet<&'a str>,
     ) {
-        if expose.type_.is_none() {
-            self.errors.push(Error::missing_field("ExposeDecl", "type"));
-        }
-        PATH.check(expose.source_path.as_ref(), "ExposeDecl", "source_path", &mut self.errors);
+        self.validate_capability(expose.capability.as_ref(), "ExposeDecl");
         match expose.source.as_ref() {
             Some(r) => match r {
                 fsys::RelativeId::Myself(_) => {}
@@ -233,10 +250,7 @@ impl<'a> ValidationContext<'a> {
         offer: &'a fsys::OfferDecl,
         prev_target_paths: &mut PathMap<'a>,
     ) {
-        if offer.type_.is_none() {
-            self.errors.push(Error::missing_field("OfferDecl", "type"));
-        }
-        PATH.check(offer.source_path.as_ref(), "OfferDecl", "source_path", &mut self.errors);
+        self.validate_capability(offer.capability.as_ref(), "OfferDecl");
         match offer.source.as_ref() {
             Some(r) => match r {
                 fsys::RelativeId::Realm(_) => {}
@@ -355,8 +369,8 @@ mod tests {
     use {
         super::*,
         fidl_fuchsia_sys2::{
-            CapabilityType, ChildDecl, ChildId, ComponentDecl, ExposeDecl, OfferDecl, OfferTarget,
-            RealmId, RelativeId, SelfId, StartupMode, UseDecl,
+            Capability, ChildDecl, ChildId, ComponentDecl, ExposeDecl, OfferDecl, OfferTarget,
+            RealmId, RelativeId, SelfId, ServiceCapability, StartupMode, UseDecl,
         },
     };
 
@@ -519,15 +533,13 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.uses = Some(vec![UseDecl{
-                    type_: None,
-                    source_path: None,
+                    capability: None,
                     target_path: None,
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::missing_field("UseDecl", "type"),
-                Error::missing_field("UseDecl", "source_path"),
+                Error::missing_field("UseDecl", "capability"),
                 Error::missing_field("UseDecl", "target_path"),
             ])),
         },
@@ -535,14 +547,15 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.uses = Some(vec![UseDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("foo/".to_string()),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("foo/".to_string()),
+                    })),
                     target_path: Some("/".to_string()),
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::invalid_field("UseDecl", "source_path"),
+                Error::invalid_field("UseDecl", "capability.path"),
                 Error::invalid_field("UseDecl", "target_path"),
             ])),
         },
@@ -550,14 +563,15 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.uses = Some(vec![UseDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some(format!("/{}", "a".repeat(1024))),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some(format!("/{}", "a".repeat(1024))),
+                    })),
                     target_path: Some(format!("/{}", "b".repeat(1024))),
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::field_too_long("UseDecl", "source_path"),
+                Error::field_too_long("UseDecl", "capability.path"),
                 Error::field_too_long("UseDecl", "target_path"),
             ])),
         },
@@ -567,16 +581,14 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![ExposeDecl{
-                    type_: None,
-                    source_path: None,
+                    capability: None,
                     source: None,
                     target_path: None,
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::missing_field("ExposeDecl", "type"),
-                Error::missing_field("ExposeDecl", "source_path"),
+                Error::missing_field("ExposeDecl", "capability"),
                 Error::missing_field("ExposeDecl", "source"),
                 Error::missing_field("ExposeDecl", "target_path"),
             ])),
@@ -585,15 +597,16 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![ExposeDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("foo/".to_string()),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("foo/".to_string()),
+                    })),
                     source: Some(RelativeId::Child(ChildId{name: Some("^bad".to_string())})),
                     target_path: Some("/".to_string()),
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::invalid_field("ExposeDecl", "source_path"),
+                Error::invalid_field("ExposeDecl", "capability.path"),
                 Error::invalid_field("ExposeDecl", "source.child.name"),
                 Error::invalid_field("ExposeDecl", "target_path"),
             ])),
@@ -602,15 +615,16 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![ExposeDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some(format!("/{}", "a".repeat(1024))),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some(format!("/{}", "a".repeat(1024))),
+                    })),
                     source: Some(RelativeId::Child(ChildId{name: Some("b".repeat(101))})),
                     target_path: Some(format!("/{}", "b".repeat(1024))),
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::field_too_long("ExposeDecl", "source_path"),
+                Error::field_too_long("ExposeDecl", "capability.path"),
                 Error::field_too_long("ExposeDecl", "source.child.name"),
                 Error::field_too_long("ExposeDecl", "target_path"),
             ])),
@@ -620,9 +634,10 @@ mod tests {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![
                     ExposeDecl{
-                        type_: Some(CapabilityType::Service),
-                        source_path: Some("/loggers/fuchsia.logger.Log".to_string()),
-                        source: Some(RelativeId::Realm(RealmId{dummy: None})),
+                        capability: Some(Capability::Service(ServiceCapability{
+                            path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        })),
+                        source: Some(RelativeId::Realm(RealmId{})),
                         target_path: Some("/svc/fuchsia.logger.Log".to_string()),
                     },
                 ]);
@@ -637,8 +652,9 @@ mod tests {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![
                     ExposeDecl{
-                        type_: Some(CapabilityType::Service),
-                        source_path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        capability: Some(Capability::Service(ServiceCapability{
+                            path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        })),
                         source: Some(RelativeId::Child(ChildId {
                             name: Some("netstack".to_string()),
                         })),
@@ -656,15 +672,17 @@ mod tests {
                 let mut decl = new_component_decl();
                 decl.exposes = Some(vec![
                     ExposeDecl{
-                        type_: Some(CapabilityType::Service),
-                        source_path: Some("/svc/logger".to_string()),
-                        source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                        capability: Some(Capability::Service(ServiceCapability{
+                            path: Some("/svc/logger".to_string()),
+                        })),
+                        source: Some(RelativeId::Myself(SelfId{})),
                         target_path: Some("/svc/fuchsia.logger.Log".to_string()),
                     },
                     ExposeDecl{
-                        type_: Some(CapabilityType::Service),
-                        source_path: Some("/svc/logger2".to_string()),
-                        source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                        capability: Some(Capability::Service(ServiceCapability{
+                            path: Some("/svc/logger2".to_string()),
+                        })),
+                        source: Some(RelativeId::Myself(SelfId{})),
                         target_path: Some("/svc/fuchsia.logger.Log".to_string()),
                     },
                 ]);
@@ -680,16 +698,14 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: None,
-                    source_path: None,
+                    capability: None,
                     source: None,
                     targets: None,
                 }]);
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::missing_field("OfferDecl", "type"),
-                Error::missing_field("OfferDecl", "source_path"),
+                Error::missing_field("OfferDecl", "capability"),
                 Error::missing_field("OfferDecl", "source"),
                 Error::missing_field("OfferDecl", "targets"),
             ])),
@@ -698,8 +714,9 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some(format!("/{}", "a".repeat(1024))),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some(format!("/{}", "a".repeat(1024))),
+                    })),
                     source: Some(RelativeId::Child(ChildId{name: Some("a".repeat(101))})),
                     targets: Some(vec![
                         OfferTarget{
@@ -711,7 +728,7 @@ mod tests {
                 decl
             },
             result = Err(ErrorList::new(vec![
-                Error::field_too_long("OfferDecl", "source_path"),
+                Error::field_too_long("OfferDecl", "capability.path"),
                 Error::field_too_long("OfferDecl", "source.child.name"),
                 Error::field_too_long("OfferTarget", "target_path"),
                 Error::field_too_long("OfferTarget", "child_name"),
@@ -722,8 +739,9 @@ mod tests {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![
                     OfferDecl{
-                        type_: Some(CapabilityType::Service),
-                        source_path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        capability: Some(Capability::Service(ServiceCapability{
+                            path: Some("/loggers/fuchsia.logger.Log".to_string()),
+                        })),
                         source: Some(RelativeId::Child(ChildId{name: Some("logger".to_string())})),
                         targets: Some(vec![
                             OfferTarget{
@@ -750,9 +768,10 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("/svc/logger".to_string()),
-                    source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("/svc/logger".to_string()),
+                    })),
+                    source: Some(RelativeId::Myself(SelfId{})),
                     targets: Some(vec![OfferTarget{target_path: None, child_name: None}]),
                 }]);
                 decl
@@ -766,9 +785,10 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("/svc/logger".to_string()),
-                    source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("/svc/logger".to_string()),
+                    })),
+                    source: Some(RelativeId::Myself(SelfId{})),
                     targets: Some(vec![]),
                 }]);
                 decl
@@ -781,8 +801,9 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("/svc/logger".to_string()),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("/svc/logger".to_string()),
+                    })),
                     source: Some(RelativeId::Child(ChildId{name: Some("logger".to_string())})),
                     targets: Some(vec![OfferTarget{
                         target_path: Some("/svc/logger".to_string()),
@@ -804,9 +825,10 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("/svc/logger".to_string()),
-                    source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("/svc/logger".to_string()),
+                    })),
+                    source: Some(RelativeId::Myself(SelfId{})),
                     targets: Some(vec![
                         OfferTarget{
                             target_path: Some("/svc/fuchsia.logger.Log".to_string()),
@@ -835,9 +857,10 @@ mod tests {
             input = {
                 let mut decl = new_component_decl();
                 decl.offers = Some(vec![OfferDecl{
-                    type_: Some(CapabilityType::Service),
-                    source_path: Some("/svc/logger".to_string()),
-                    source: Some(RelativeId::Myself(SelfId{dummy: None})),
+                    capability: Some(Capability::Service(ServiceCapability{
+                        path: Some("/svc/logger".to_string()),
+                    })),
+                    source: Some(RelativeId::Myself(SelfId{})),
                     targets: Some(vec![
                         OfferTarget{
                             target_path: Some("/svc/fuchsia.logger.Log".to_string()),
diff --git a/garnet/lib/rust/cm_json/cm_schema.json b/garnet/lib/rust/cm_json/cm_schema.json
index 4c3d21a95367b5cdb147ade0b1980e46dd4676d2..eaac035f2ca9d1f78a6e9c6578bae53685a7d7e9 100644
--- a/garnet/lib/rust/cm_json/cm_schema.json
+++ b/garnet/lib/rust/cm_json/cm_schema.json
@@ -53,6 +53,7 @@
         "child": {
           "type": "object",
           "title": "Component's child",
+          "required": [ "name" ],
           "properties": {
             "name": {
               "title": "Child name",
@@ -61,6 +62,43 @@
           }
         }
       }
+    },
+    "capability-clause": {
+      "type": "object",
+      "oneOf": [
+        {
+          "required": [ "service" ]
+        },
+        {
+          "required": [ "directory" ]
+        }
+      ],
+      "properties": {
+        "service": {
+          "type": "object",
+          "title": "Service capability",
+          "required": [ "path" ],
+          "properties": {
+            "path": {
+              "type": "string",
+              "title": "Capability path",
+              "allOf": [{ "$ref": "#/definitions/path-clause" }]
+            }
+          }
+        },
+        "directory": {
+          "type": "object",
+          "title": "Directory capability",
+          "required": [ "path" ],
+          "properties": {
+            "path": {
+              "type": "string",
+              "title": "Capability path",
+              "allOf": [{ "$ref": "#/definitions/path-clause" }]
+            }
+          }
+        }
+      }
     }
   },
   "properties": {
@@ -75,18 +113,13 @@
       "items": {
         "type": "object",
         "required": [
-          "type",
-          "source_path",
+          "capability",
           "target_path"
         ],
         "properties": {
-          "type": {
-            "title": "Used capability type",
-            "$ref": "#/definitions/capability-clause"
-          },
-          "source_path": {
-            "allOf": [{ "$ref": "#/definitions/path-clause" }],
-            "title": "Used capability source path"
+          "capability": {
+            "title": "Used capability",
+            "allOf": [{ "$ref": "#/definitions/capability-clause" }]
           },
           "target_path": {
             "allOf": [{ "$ref": "#/definitions/path-clause" }],
@@ -102,19 +135,14 @@
       "items": {
         "type": "object",
         "required": [
-          "type",
-          "source_path",
+          "capability",
           "source",
           "target_path"
         ],
         "properties": {
-          "type": {
-            "title": "Exposed capability type",
-            "$ref": "#/definitions/capability-clause"
-          },
-          "source_path": {
-            "allOf": [{ "$ref": "#/definitions/path-clause" }],
-            "title": "Exposed capability source path"
+          "capability": {
+            "title": "Exposed capability",
+            "allOf": [{ "$ref": "#/definitions/capability-clause" }]
           },
           "source": {
             "title": "Exposed capability source component",
@@ -134,24 +162,14 @@
       "items": {
         "type": "object",
         "required": [
-          "type",
-          "source_path",
+          "capability",
           "source",
           "targets"
         ],
         "properties": {
-          "type": {
-            "title": "Offered capability type",
-            "$ref": "#/definitions/capability-clause"
-          },
-          "source_path": {
-            "allOf": [{ "$ref": "#/definitions/path-clause" }],
-            "title": "Offered capability source path"
-          },
-          "source": {
-            "type": "object",
-            "title": "Offered capability source component",
-            "allOf": [ { "$ref": "#/definitions/relative-id-clause" } ]
+          "capability": {
+            "title": "Offered capability",
+            "allOf": [{ "$ref": "#/definitions/capability-clause" }]
           },
           "targets": {
             "type": "array",
diff --git a/garnet/lib/rust/cm_json/src/cm.rs b/garnet/lib/rust/cm_json/src/cm.rs
index acf1df8d5672cf0ecdc7655d496a28bdf769dcf4..415171b19ee0ddf8143a995adb4be20bcec8c0b0 100644
--- a/garnet/lib/rust/cm_json/src/cm.rs
+++ b/garnet/lib/rust/cm_json/src/cm.rs
@@ -24,23 +24,20 @@ pub struct Document {
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct Use {
-    pub r#type: String,
-    pub source_path: String,
+    pub capability: Capability,
     pub target_path: String,
 }
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct Expose {
-    pub r#type: String,
-    pub source_path: String,
+    pub capability: Capability,
     pub source: Source,
     pub target_path: String,
 }
 
 #[derive(Serialize, Deserialize, Debug)]
 pub struct Offer {
-    pub r#type: String,
-    pub source_path: String,
+    pub capability: Capability,
     pub source: Source,
     pub targets: Vec<Target>,
 }
@@ -53,13 +50,21 @@ pub struct Child {
 }
 
 #[derive(Serialize, Deserialize, Debug)]
-pub struct Source {
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub realm: Option<RealmId>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub myself: Option<SelfId>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub child: Option<ChildId>,
+pub enum Capability {
+    #[serde(rename = "service")]
+    Service(Service),
+    #[serde(rename = "directory")]
+    Directory(Directory),
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub enum Source {
+    #[serde(rename = "realm")]
+    Realm(RealmId),
+    #[serde(rename = "myself")]
+    Myself(SelfId),
+    #[serde(rename = "child")]
+    Child(ChildId),
 }
 
 #[derive(Serialize, Deserialize, Debug)]
@@ -68,6 +73,16 @@ pub struct Target {
     pub child_name: String,
 }
 
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Service {
+    pub path: String,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Directory {
+    pub path: String,
+}
+
 #[derive(Serialize, Deserialize, Debug)]
 pub struct RealmId {}
 
diff --git a/garnet/lib/rust/cm_rust/src/lib.rs b/garnet/lib/rust/cm_rust/src/lib.rs
index 81c472b02b7efefaa15a1813d4564df1a94a769a..ba16d791ae0cadcf3d38b3623e42aa154e664207 100644
--- a/garnet/lib/rust/cm_rust/src/lib.rs
+++ b/garnet/lib/rust/cm_rust/src/lib.rs
@@ -158,32 +158,40 @@ impl Clone for ComponentDecl {
 }
 
 impl ComponentDecl {
-    /// Returns the ExposeDecl that exposes a capability under `target_path` with `type`, if it
-    /// exists.
+    /// Returns the ExposeDecl that exposes `capability`, if it exists.
     pub fn find_expose_source<'a>(
         &'a self,
-        target_path: &CapabilityPath,
-        type_: &fsys::CapabilityType,
+        capability: &Capability,
     ) -> Option<&'a ExposeDecl> {
-        self.exposes.iter().find(|&e| e.target_path == *target_path && e.type_ == *type_)
+        self.exposes.iter().find(|&e| {
+            e.target_path == *capability.path()
+                && match (capability, &e.capability) {
+                    (Capability::Service(_), Capability::Service(_)) => true,
+                    (Capability::Directory(_), Capability::Directory(_)) => true,
+                    _ => false,
+                }
+        })
     }
 
     /// Returns the OfferDecl that offers a capability under `target_path` to `child_name` with
     /// the given `type_`, if it exists.
     pub fn find_offer_source<'a>(
         &'a self,
-        target_path: &CapabilityPath,
-        type_: &fsys::CapabilityType,
+        capability: &Capability,
         child_name: &str,
     ) -> Option<&'a OfferDecl> {
         for offer in self.offers.iter() {
-            if offer.type_ != *type_ {
-                continue;
+            match (capability, &offer.capability) {
+                (Capability::Service(_), Capability::Service(_)) => {}
+                (Capability::Directory(_), Capability::Directory(_)) => {}
+                _ => {
+                    continue;
+                }
             }
             if let Some(_) = offer
                 .targets
                 .iter()
-                .find(|&e| e.target_path == *target_path && e.child_name == *child_name)
+                .find(|&e| e.target_path == *capability.path() && e.child_name == *child_name)
             {
                 return Some(offer);
             }
@@ -194,21 +202,18 @@ impl ComponentDecl {
 
 fidl_into_vec!(UseDecl, UseDecl, fsys::UseDecl, fsys::UseDecl,
                {
-                   type_: fsys::CapabilityType,
-                   source_path: CapabilityPath,
+                   capability: Capability,
                    target_path: CapabilityPath,
                });
 fidl_into_vec!(ExposeDecl, ExposeDecl, fsys::ExposeDecl, fsys::ExposeDecl,
                {
-                   type_: fsys::CapabilityType,
-                   source_path: CapabilityPath,
+                   capability: Capability,
                    source: RelativeId,
                    target_path: CapabilityPath,
                });
 fidl_into_vec!(OfferDecl, OfferDecl, fsys::OfferDecl, fsys::OfferDecl,
                {
-                   type_: fsys::CapabilityType,
-                   source_path: CapabilityPath,
+                   capability: Capability,
                    source: RelativeId,
                    targets: Vec<OfferTarget>,
                });
@@ -224,7 +229,6 @@ fidl_into_vec!(OfferTarget, OfferTarget, fsys::OfferTarget, fsys::OfferTarget,
                    child_name: String,
                });
 fidl_translations_opt_type!(String);
-fidl_translations_opt_type!(fsys::CapabilityType);
 fidl_translations_opt_type!(fsys::StartupMode);
 fidl_translations_opt_type!(fdata::Dictionary);
 fidl_translations_identical!(Option<fdata::Dictionary>);
@@ -335,6 +339,57 @@ fn from_fidl_dict(dict: fdata::Dictionary) -> HashMap<String, Value> {
     dict.entries.into_iter().map(|e| (e.key, e.value.fidl_into_native())).collect()
 }
 
+#[derive(Debug, Clone, PartialEq)]
+pub enum Capability {
+    Service(CapabilityPath),
+    Directory(CapabilityPath),
+}
+
+impl Capability {
+    pub fn path(&self) -> &CapabilityPath {
+        match self {
+            Capability::Service(s) => s,
+            Capability::Directory(d) => d,
+        }
+    }
+}
+
+impl fmt::Display for Capability {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Capability::Service(s) => {
+                write!(f, "service at {}", s)
+            }
+            Capability::Directory(d) => {
+                write!(f, "directory at {}", d)
+            }
+        }
+    }
+}
+
+impl FidlIntoNative<Capability> for Option<fsys::Capability> {
+    fn fidl_into_native(self) -> Capability {
+        match self.unwrap() {
+            fsys::Capability::Service(s) => Capability::Service(s.path.fidl_into_native()),
+            fsys::Capability::Directory(d) => Capability::Directory(d.path.fidl_into_native()),
+            fsys::Capability::__UnknownVariant { .. } => panic!("unknown Capability variant"),
+        }
+    }
+}
+
+impl NativeIntoFidl<Option<fsys::Capability>> for Capability {
+    fn native_into_fidl(self) -> Option<fsys::Capability> {
+        Some(match self {
+            Capability::Service(p) => {
+                fsys::Capability::Service(fsys::ServiceCapability { path: p.native_into_fidl() })
+            }
+            Capability::Directory(p) => fsys::Capability::Directory(fsys::DirectoryCapability {
+                path: p.native_into_fidl(),
+            }),
+        })
+    }
+}
+
 #[derive(Debug, Clone, PartialEq)]
 pub enum RelativeId {
     Realm,
@@ -348,7 +403,7 @@ impl FidlIntoNative<RelativeId> for Option<fsys::RelativeId> {
             fsys::RelativeId::Realm(_) => RelativeId::Realm,
             fsys::RelativeId::Myself(_) => RelativeId::Myself,
             fsys::RelativeId::Child(c) => RelativeId::Child(c.name.unwrap()),
-            fsys::RelativeId::__UnknownVariant{..} => { panic!("unknown RelativeId variant") },
+            fsys::RelativeId::__UnknownVariant { .. } => panic!("unknown RelativeId variant"),
         }
     }
 }
@@ -356,8 +411,8 @@ impl FidlIntoNative<RelativeId> for Option<fsys::RelativeId> {
 impl NativeIntoFidl<Option<fsys::RelativeId>> for RelativeId {
     fn native_into_fidl(self) -> Option<fsys::RelativeId> {
         Some(match self {
-            RelativeId::Realm => fsys::RelativeId::Realm(fsys::RealmId { dummy: None }),
-            RelativeId::Myself => fsys::RelativeId::Myself(fsys::SelfId { dummy: None }),
+            RelativeId::Realm => fsys::RelativeId::Realm(fsys::RealmId {}),
+            RelativeId::Myself => fsys::RelativeId::Myself(fsys::SelfId {}),
             RelativeId::Child(child_name) => {
                 fsys::RelativeId::Child(fsys::ChildId { name: Some(child_name) })
             }
@@ -540,15 +595,17 @@ mod tests {
                ]}),
                uses: Some(vec![
                    fsys::UseDecl{
-                       type_: Some(fsys::CapabilityType::Directory),
-                       source_path: Some("/data/dir".to_string()),
+                       capability: Some(fsys::Capability::Directory(fsys::DirectoryCapability {
+                           path: Some("/data/dir".to_string()),
+                       })),
                        target_path: Some("/data".to_string()),
                    },
                ]),
                exposes: Some(vec![
                    fsys::ExposeDecl {
-                       type_: Some(fsys::CapabilityType::Service),
-                       source_path: Some("/svc/mynetstack".to_string()),
+                       capability: Some(fsys::Capability::Service(fsys::ServiceCapability {
+                           path: Some("/svc/mynetstack".to_string()),
+                       })),
                        source: Some(fsys::RelativeId::Child(fsys::ChildId {
                            name: Some("netstack".to_string()),
                        })),
@@ -557,9 +614,10 @@ mod tests {
                ]),
                offers: Some(vec![
                    fsys::OfferDecl {
-                       type_: Some(fsys::CapabilityType::Service),
-                       source_path: Some("/svc/sys_logger".to_string()),
-                       source: Some(fsys::RelativeId::Realm(fsys::RealmId{dummy: None})),
+                       capability: Some(fsys::Capability::Service(fsys::ServiceCapability {
+                           path: Some("/svc/sys_logger".to_string()),
+                       })),
+                       source: Some(fsys::RelativeId::Realm(fsys::RealmId {})),
                        targets: Some(vec![
                            fsys::OfferTarget{
                                target_path: Some("/svc/logger".to_string()),
@@ -599,26 +657,23 @@ mod tests {
                     ]}),
                     uses: vec![
                         UseDecl {
-                            type_: fsys::CapabilityType::Directory,
-                            source_path: "/data/dir".try_into().unwrap(),
+                            capability: Capability::Directory("/data/dir".try_into().unwrap()),
                             target_path: "/data".try_into().unwrap(),
                         },
                     ],
                     exposes: vec![
                         ExposeDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: "/svc/mynetstack".try_into().unwrap(),
+                            capability: Capability::Service("/svc/mynetstack".try_into().unwrap()),
                             source: RelativeId::Child("netstack".to_string()),
                             target_path: "/svc/netstack".try_into().unwrap(),
                         },
                     ],
                     offers: vec![
                         OfferDecl {
-                            type_: fsys::CapabilityType::Service,
-                            source_path: "/svc/sys_logger".try_into().unwrap(),
+                            capability: Capability::Service("/svc/sys_logger".try_into().unwrap()),
                             source: RelativeId::Realm,
                             targets: vec![
-                                OfferTarget{
+                                OfferTarget {
                                     target_path: "/svc/logger".try_into().unwrap(),
                                     child_name: "echo".to_string(),
                                 },
@@ -688,11 +743,11 @@ mod tests {
 
     test_fidl_into_and_from! {
         fidl_into_relative_id_realm => {
-            input = Some(fsys::RelativeId::Realm(fsys::RealmId{dummy: None})),
+            input = Some(fsys::RelativeId::Realm(fsys::RealmId {})),
             result = RelativeId::Realm,
         },
         fidl_into_relative_id_myself => {
-            input = Some(fsys::RelativeId::Myself(fsys::SelfId{dummy: None})),
+            input = Some(fsys::RelativeId::Myself(fsys::SelfId {})),
             result = RelativeId::Myself,
         },
         fidl_into_relative_id_child => {
diff --git a/sdk/fidl/fuchsia.sys2/decls/capability.fidl b/sdk/fidl/fuchsia.sys2/decls/capability.fidl
index f79acdf71bca301f4990c60817d8d2ddd1e09767..b2beba8e555f1c03b2f20b38e9f5a0580d72bb83 100644
--- a/sdk/fidl/fuchsia.sys2/decls/capability.fidl
+++ b/sdk/fidl/fuchsia.sys2/decls/capability.fidl
@@ -4,8 +4,32 @@
 
 library fuchsia.sys2;
 
-/// Specifies a type of capability that can be offered between components.
-enum CapabilityType {
-  SERVICE = 0;
-  DIRECTORY = 1;
+/// A capability that can be exchanged between components.
+xunion Capability {
+    ServiceCapability service;
+    DirectoryCapability directory;
+};
+
+/// Represents a capability for a service.
+table ServiceCapability {
+    /// Path identifying the service.
+    ///
+    /// If the capability is exposed or offered from |source| == |SELF|, this
+    /// is a path in the component’s namespace. Otherwise, it is the path by
+    /// which the capability was presented to the component.
+    ///
+    /// Must be an absolute path starting with /.
+    1: string:MAX_PATH_LENGTH path;
+};
+
+/// Represents a capability for a directory.
+table DirectoryCapability {
+    /// Path identifying the directory.
+    ///
+    /// If the capability is exposed or offered from |source| == |SELF|, this
+    /// is a path in the component’s namespace. Otherwise, it is the path by
+    /// which the capability was presented to the component.
+    ///
+    /// Must be an absolute path starting with /.
+    1: string:MAX_PATH_LENGTH path;
 };
diff --git a/sdk/fidl/fuchsia.sys2/decls/expose_decl.fidl b/sdk/fidl/fuchsia.sys2/decls/expose_decl.fidl
index 212f3dbd31ced00e93a56ea4da38f4df61ddc638..3758b111a5ec8c4d876d079d256632811542795a 100644
--- a/sdk/fidl/fuchsia.sys2/decls/expose_decl.fidl
+++ b/sdk/fidl/fuchsia.sys2/decls/expose_decl.fidl
@@ -7,25 +7,16 @@ library fuchsia.sys2;
 /// Declares a capability exposed to a component's containing realm, such as a
 /// service exposed by the component or one of its children at runtime.
 table ExposeDecl {
-    /// The type of capability exposed.
-    1: CapabilityType type;
+    /// The capability being exposed.
+    1: Capability capability;
 
-    /// The incoming path to the capability.
+    /// The provider of the capability relative to the component itself.
     ///
-    /// If |source| == |SELF|, this is a path in the component’s namespace.
-    /// Otherwise, it is the path by which the capability was presented to the
-    /// component.
-    ///
-    /// Must be an absolute path starting with /.
-    2: string:MAX_PATH_LENGTH source_path;
-
-    /// The provider of the service relative to the component itself.
-    ///
-    /// Valid relations: self, child.
-    3: RelativeId source;
+    /// Valid relations: myself, child.
+    2: RelativeId source;
 
     /// The path by which the capability is being exposed.
     ///
     /// Must be an absolute path starting with /.
-    4: string:MAX_PATH_LENGTH target_path;
+    3: string:MAX_PATH_LENGTH target_path;
 };
diff --git a/sdk/fidl/fuchsia.sys2/decls/offer_decl.fidl b/sdk/fidl/fuchsia.sys2/decls/offer_decl.fidl
index e7da06a0dd9d0f06dd637ffea8d335a1495e52af..0fd3974c2010b4222f3a3c7eb7988a4afe1def6f 100644
--- a/sdk/fidl/fuchsia.sys2/decls/offer_decl.fidl
+++ b/sdk/fidl/fuchsia.sys2/decls/offer_decl.fidl
@@ -8,25 +8,16 @@ library fuchsia.sys2;
 /// a service offered by the component's containing realm, the component itself,
 /// or one of its children.
 table OfferDecl {
-    /// The type of capability offered.
-    1: CapabilityType type;
-
-    /// The incoming path to the capability.
-    ///
-    /// If |source| == |SELF|, this is a path in the component’s namespace.
-    /// Otherwise, it is the path by which the capability was presented to the
-    /// component.
-    ///
-    /// Must be an absolute path starting with /.
-    2: string:MAX_PATH_LENGTH source_path;
+    /// The capability being offered.
+    1: Capability capability;
 
     /// The provider of the capability relative to the component itself.
     ///
-    /// Valid relations: realm, self, child.
-    3: RelativeId source;
+    /// Valid relations: realm, myself, child.
+    2: RelativeId source;
 
     /// The list of children to which the capability should be offered.
-    4: vector<OfferTarget> targets;
+    3: vector<OfferTarget> targets;
 };
 
 /// Describes a target for a capability offering.
diff --git a/sdk/fidl/fuchsia.sys2/decls/relative_id.fidl b/sdk/fidl/fuchsia.sys2/decls/relative_id.fidl
index ff217376ececf88e9f9a5d353e2b521e6ef4ff5b..0dd10a6a8ea85be8b293a72f25d88fe30cac72f5 100644
--- a/sdk/fidl/fuchsia.sys2/decls/relative_id.fidl
+++ b/sdk/fidl/fuchsia.sys2/decls/relative_id.fidl
@@ -12,16 +12,10 @@ xunion RelativeId {
 };
 
 /// Represents a component’s containing realm, i.e. the parent component.
-table RealmId {
-    // TODO(FIDL-592): Remove once no longer required
-    1: bool dummy;
-};
+table RealmId {};
 
 /// Represents the component itself.
-table SelfId {
-    // TODO(FIDL-592): Remove once no longer required
-    1: bool dummy;
-};
+table SelfId {};
 
 /// Represents one of the component's children.
 table ChildId {
diff --git a/sdk/fidl/fuchsia.sys2/decls/use_decl.fidl b/sdk/fidl/fuchsia.sys2/decls/use_decl.fidl
index 6677f0059e08a63a472fe5e4de1d8f090eb98f5f..98d9c558f22f2e9b642326c9c543d9d6fccbbb23 100644
--- a/sdk/fidl/fuchsia.sys2/decls/use_decl.fidl
+++ b/sdk/fidl/fuchsia.sys2/decls/use_decl.fidl
@@ -7,17 +7,12 @@ library fuchsia.sys2;
 /// Declares a capability used by a component, which was offered to the
 /// component’s environment.
 table UseDecl {
-    /// The type of capability used.
-    1: CapabilityType type;
-
-    /// The path of a capability offered to the component.
-    ///
-    /// Must be an absolute path starting with /.
-    2: string:MAX_PATH_LENGTH source_path;
+    /// The capability being used.
+    1: Capability capability;
 
     /// The path where the capability should be installed in the component's
     /// namespace.
     ///
     /// Must be an absolute path starting with /.
-    3: string:MAX_PATH_LENGTH target_path;
+    2: string:MAX_PATH_LENGTH target_path;
 };