blob: a5b3afb3b54b0c0eab88c9fa014943b55d102943 [file] [log] [blame] [view]
{% set rfcid = "RFC-0089" %}
{% include "docs/contribute/governance/rfcs/_common/_rfc_header.md" %}
# {{ rfc.name }}: {{ rfc.title }}
<!-- *** DO NOT EDIT ABOVE THIS LINE -->
<!--
*** This should begin with an H2 element (for example, ## Summary).
-->
## Summary
GN variables set in product definitions are used to generate a custom core realm
in the component framework for that product.
## Motivation
Today the core realm in CFv2 of the component framework is the component which
holds most other packaged components in the v2 system. There is a single version
of this component, which results in every product having the same set of static
v2 components and capability routes for those components. This results in both
components existing that have no purpose and will never be run, and overly broad
capabilities being offered to components, as the core realm has to be built to
be a union of all product configurations.
Additionally, the v1 component framework supports at build time conditionally
adding capabilities and components to the `sys` realm for specific products. As
components are migrated from v1 to v2, components which already depend on this
will further exacerbate the issues with the current model requiring the core
realm to have a single definition that meets the requirements of every product
at once.
Some components have already been migrated from the v1 `sys` realm into the v2
`core` realm, with an increased pace of migrations expected in the second
quarter of 2021.
Due to the above, we need the ability to tailor the exact contents of the
central structure of the CFv2 realms to fit the product on which it is running.
## Scope
This design aims to unlock additional component migrations in the very short
term until a more advanced, future-proof solution is ready. This design is not
aiming to be suitable for out of tree products, nor is it aiming to be a
suitable long-term solution. The PDK efforts, which aim to enable out of tree
product assembly, will solve the same problems addressed here in a more holistic
fashion.
## Design
The contents of the core realm manifest will be split up into a common base and
CML shards that contain components and their capability routes that are
optionally included by the product. For example, the `/core/temperature-logger`
component which is present in CFv2 today is only functional on the `astro`
product. Instead of including things relevant to `temperature-logger` in the
base core manifest, the following shard would be added in a separate file:
```
{
children: [
{
name: "temperature-logger",
url: "fuchsia-pkg://fuchsia.com/temperature-logger#meta/temperature-logger.cm",
},
],
offer: [
{
protocol: "fuchsia.thermal.test.TemperatureLogger",
from: "#temperature-logger",
to: [ "#appmgr" ],
},
{
protocol: [ "fuchsia.logger.LogSink" ],
from: "parent",
to: [ "#temperature-logger" ],
},
{
directory: "dev-class",
as: "dev-temperature",
from: "parent",
to: [ "#temperature-logger" ],
subdir: "temperature",
},
{
directory: "dev-class",
as: "dev-thermal",
from: "parent",
to: [ "#temperature-logger" ],
subdir: "thermal",
},
{
directory: "config-data",
from: "parent",
to: [ "#temperature-logger" ],
subdir: "temperature-logger",
},
{
protocol: [
"fuchsia.device.Controller",
"fuchsia.hardware.temperature.Device",
],
from: "parent",
to: [ "#temperature-logger" ],
},
{
protocol: "fuchsia.tracing.provider.Registry",
from: "#appmgr",
to: [ "#temperature-logger" ],
dependency: "weak_for_migration",
},
],
}
```
This shard will use a GN template to create a target for it, which contains the
shard's path. For our `temperature-logger` example, the target would look like
this:
```
core_shard("temperature_logger_shard") {
shard = "//meta/temperature-logger.shard.cml"
}
```
Each product's `.gni` file (such as `//products/workstation.gni`) will be able
to specify the GN targets of the shards which they would like to be included in
the product's core realm.
```
core_realm_shards += [
"//src/sys/core:temperature_logger_shard"
]
```
At product assembly time these targets are then gathered up using [GN's
`generated_file()` target][generated-file] and used as input to [CMC's merge
operation][cmc-merge], where the shards to be included in the product are merged
together with the core realm's base shard. In our current example, the shard for
`temperature-logger` is the only shard merged with the core base shard.
This generated core realm will be included in a package whose name is derived
from the product. So for example, the core manifest for the workstation product
would be packaged at `fuchsia-pkg://fuchsia.com/core-workstation#meta/core.cm`.
This is because components are identified using URLs. These identifiers follow
the webarch principles for identification, that "global naming leads to global
network effects". As such, a given component URL refers to the same logical
entity regardless of the context in which the URL exists. This approach implies
there is one universe of software for Fuchsia that spans all the product and
board configurations. Having each product be able to use the same URL to refer
to the core realm, and having the contents behind that URL vary per-product,
would not be following this principle.
Because the URL for the core realm will now be different between products, the
root component manifest is modified at build-time to include the correct URL for
the core realm for the current product. This product-specific root realm does
not need to be packaged in a varying fashion like the core realm, as it is
included directly in the ZBI, which is already product specific.
All components which are present on all products will be in the common base, and
shards will only be created for components which are not included on some
products. If a new product is added that wishes to exclude some component that
up until that point was included on all previous products, then this component
will be refactored out of the common base and into a shard.
### Sessions and product-specific routes
In scenarios where product-specific capabilities in the core realm are to be
routed through session manager to the session, there are two possible options.
One would be to have session manager route the superset of all capabilities
across all products. In this case the routing for unavailable capabilities would
fail at the core realm.
The second option would be to use a shard-based approach to also build
product-specific session manager manifests, identical to how this proposal
outlines this is done for the core realm. In this case the routing for
unavailable capabilities would fail at the session manager realm. This approach
would require the session manager and core shard lists to be kept in sync, and
add additional build complexity and maintenance costs.
Both of these options would appear identical from the perspective of the
session.
## Implementation
This change can be made in a single gerrit CL. As GN arguments have default
values, product definitions can add overrides to enable features they want at a
later time.
An incomplete yet functional implementation, demonstrating how this approach
works, can be found [here][wip-cl].
## Performance
As all of the work in this proposal happens at build-time, there will not be any
run-time performance impact.
## Security considerations
This proposal would result in components that should not be run on a product not
existing on that product. It will also enable us to provide components with the
capabilities they need for the product on which they are running, instead of
always giving components the union of capabilities they may need across
products.
This proposal would result in multiple possible variations of the CFv2 realm
structure, which would result in security audits and tools (such as scrutiny)
needing to be able to handle the new mechanics along with less of a shared base
between products.
## Privacy considerations
This proposal would result in components only existing on the products on which
they should run and never receiving an overly broad set of capabilities, both of
which have the potential to improve the system's privacy guarantees.
## Testing
Product owners will need to ensure that required components are included on
their products, and that the presence of these components is covered in testing.
While this is already true due to product-specific package sets, the core realm
variations proposed here add an additional point at which product definitions
could accidentally omit an important component. This results in a slightly
higher burden on product owners to ensure that test configurations remain
consistent with product configurations.
## Documentation
The exact GN arguments available to product owners to set will be documented at
the place they are defined in GN. Additionally, markdown documentation will be
maintained describing each manifest shard and the impact it will have on the
product's core realm.
[build-policy]: /docs/development/build/build_system/policies.md
[wip-cl]: https://fuchsia-review.googlesource.com/c/fuchsia/+/486644
[generated-file]: https://gn.googlesource.com/gn/+/master/docs/reference.md#func_generated_file
[cmc-merge]: /tools/cmc/build/cmc.gni