///|
/// A path selection, not a filesystem grant. The host resolves it from its
/// configuration origin and enforces its own accepted roots.
#derive(Eq, Debug)
pub(all) struct MetadataPath {
path : String
origin : String
}
///|
pub extend MetadataPath with Eq::{equal, not_equal}
///|
pub extend MetadataPath with @debug.Debug::{to_repr}
///|
#derive(Eq, Debug)
pub(all) struct MetadataRestoreConfig {
service : MetadataPath
policy : MetadataPath
lock : MetadataPath
registry : MetadataPath
state : MetadataPath
release : String
assurance : String
}
///|
pub extend MetadataRestoreConfig with Eq::{equal, not_equal}
///|
pub extend MetadataRestoreConfig with @debug.Debug::{to_repr}
///|
/// Immutable service selections for a host binder. Disabled requests no CLI
/// service; it does not revoke capabilities explicitly granted by an embedding.
/// Parsing performs no restoration,
/// trust initialization or capability acquisition.
#derive(Eq, Debug)
pub(all) enum MetadataProviderRequest {
Disabled
SharedLocalRestore(MetadataRestoreConfig)
}
///|
pub extend MetadataProviderRequest with Eq::{equal, not_equal}
///|
pub extend MetadataProviderRequest with @debug.Debug::{to_repr}
///|
fn metadata_origin(document : Document, key : String) -> String {
document.provenance
.get(key)
.unwrap_or(
document.provenance.get("metadata.provider").unwrap_or(""),
)
}
///|
fn[T] metadata_invalid(
document : Document,
key : String,
detail : String,
) -> T raise {
raise Invalid(
"metadata.invalid_configuration: " +
key +
" " +
detail +
" (set in " +
metadata_origin(document, key) +
")",
)
}
///|
fn metadata_text(document : Document, key : String) -> String raise {
match document.json(key) {
Some(String(text)) if text.trim() != "" && !text.contains("\u0000") => text
None => metadata_invalid(document, key, "is required")
_ => metadata_invalid(document, key, "must be a nonempty string")
}
}
///|
fn metadata_path(document : Document, key : String) -> MetadataPath raise {
{
path: metadata_text(document, key),
origin: metadata_origin(document, key),
}
}
///|
fn metadata_release_segment(text : StringView) -> Bool {
text != "" &&
text
.split("-")
.collect()
.all(part => {
part != "" &&
part
.to_owned()
.to_array()
.all(c => (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
})
}
///|
fn exact_provider_release(text : String) -> Bool {
let selection = text.split("@").collect()
if selection.length() != 2 {
return false
}
let package_parts = selection[0].split("/").collect()
if package_parts.length() < 2 || !package_parts[0].contains(".") {
return false
}
if !package_parts[0].split(".").collect().all(metadata_release_segment) ||
!package_parts[1:].all(metadata_release_segment) {
return false
}
let parts = selection[1].split(".").collect()
parts.length() == 3 &&
parts.all(p => {
p != "" &&
(p == "0" || !p.has_prefix("0")) &&
p.to_owned().to_array().all(c => c >= '0' && c <= '9')
})
}
///|
/// Read only the owned provider selections. Other metadata configuration stays
/// available to its own consumers. Release semantics are finally checked by the
/// shared restore service; this parser admits canonical stable release syntax.
pub fn Document::metadata_provider_request(
self : Document,
) -> MetadataProviderRequest raise {
match self.json("metadata") {
None | Some(Object(_)) => ()
_ => metadata_invalid(self, "metadata", "must be a table")
}
match self.json("metadata.naming") {
None | Some(Object(_)) => ()
_ => metadata_invalid(self, "metadata.naming", "must be a table")
}
let provider = match self.json("metadata.provider") {
None => "none"
Some(String(text)) => text
_ => metadata_invalid(self, "metadata.provider", "must be a string")
}
if provider == "none" {
for
key in [
"metadata.service", "metadata.policy", "metadata.lock", "metadata.registry",
"metadata.state", "metadata.assurance", "metadata.naming.release",
] {
if self.json(key) is Some(_) {
metadata_invalid(
self, key, "requires metadata.provider = 'shared-local-restore'",
)
}
}
return Disabled
}
if provider != "shared-local-restore" {
metadata_invalid(
self, "metadata.provider", "must be 'none' or 'shared-local-restore'",
)
}
let service = metadata_path(self, "metadata.service")
let policy = metadata_path(self, "metadata.policy")
let lock = metadata_path(self, "metadata.lock")
let registry = metadata_path(self, "metadata.registry")
let state = metadata_path(self, "metadata.state")
let assurance = metadata_text(self, "metadata.assurance")
if assurance != "portable" {
metadata_invalid(
self, "metadata.assurance", "must be 'portable'; hardened is unavailable",
)
}
let release = metadata_text(self, "metadata.naming.release")
if !exact_provider_release(release) {
metadata_invalid(
self, "metadata.naming.release", "must be an authority-qualified PACKAGE@MAJOR.MINOR.PATCH release; the IR name morphir/naming is checked separately",
)
}
SharedLocalRestore({
service,
policy,
lock,
registry,
state,
release,
assurance,
})
}