lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

package_boundary.rs (9477B)


      1 use std::collections::BTreeSet;
      2 
      3 const MANIFEST: &str = include_str!("../Cargo.toml");
      4 const README: &str = include_str!("../README.md");
      5 const PUBLIC_API: &str = include_str!("../../../contracts/api_baselines/radroots_service_host.txt");
      6 const ROOT: &str = include_str!("../src/lib.rs");
      7 const CONFIG_DOCUMENT_SOURCE: &str = include_str!("../src/config/document.rs");
      8 const CONFIG_VALUE_SOURCE: &str = include_str!("../src/config/value.rs");
      9 const ADMIN_SOURCE: &str = concat!(
     10     include_str!("../src/admin/mod.rs"),
     11     include_str!("../src/admin/client.rs"),
     12     include_str!("../src/admin/limits.rs"),
     13     include_str!("../src/admin/model.rs"),
     14     include_str!("../src/admin/peer.rs"),
     15     include_str!("../src/admin/server.rs"),
     16     include_str!("../src/admin/unix.rs"),
     17 );
     18 const STATUS_SOURCE: &str = concat!(
     19     include_str!("../src/status/mod.rs"),
     20     include_str!("../src/status/phase.rs"),
     21     include_str!("../src/status/reason.rs"),
     22     include_str!("../src/status/service.rs"),
     23 );
     24 const LIFECYCLE_SOURCE: &str = concat!(
     25     include_str!("../src/lifecycle/mod.rs"),
     26     include_str!("../src/lifecycle/cancel.rs"),
     27     include_str!("../src/lifecycle/shutdown.rs"),
     28     include_str!("../src/lifecycle/signal.rs"),
     29     include_str!("../src/lifecycle/supervisor.rs"),
     30     include_str!("../src/lifecycle/task.rs"),
     31 );
     32 const OPERATIONS_PRIMITIVES_SOURCE: &str = concat!(
     33     include_str!("../src/operations/mod.rs"),
     34     include_str!("../src/operations/config.rs"),
     35     include_str!("../src/operations/health.rs"),
     36     include_str!("../src/operations/metrics.rs"),
     37 );
     38 const OPERATIONS_SOURCE: &str = concat!(
     39     include_str!("../src/operations/mod.rs"),
     40     include_str!("../src/operations/server.rs"),
     41 );
     42 
     43 #[test]
     44 fn service_host_is_unpublished_lint_governed_and_dependency_bounded() {
     45     for required in [
     46         "name = \"radroots_service_host\"",
     47         "publish = false",
     48         "version = \"0.1.0-alpha\"",
     49         "[lints]\nworkspace = true",
     50     ] {
     51         assert!(
     52             MANIFEST.contains(required),
     53             "manifest is missing `{required}`"
     54         );
     55     }
     56 
     57     assert_eq!(
     58         dependency_keys(MANIFEST),
     59         BTreeSet::from([
     60             "bytes",
     61             "fs2",
     62             "getrandom",
     63             "http",
     64             "http-body-util",
     65             "hyper",
     66             "hyper-util",
     67             "radroots_runtime_paths",
     68             "rustix",
     69             "serde",
     70             "serde_json",
     71             "tokio",
     72             "tokio-util",
     73             "toml",
     74         ])
     75     );
     76     assert!(public_modules(ROOT).is_empty());
     77     assert_eq!(
     78         private_modules(ROOT),
     79         BTreeSet::from([
     80             "admin",
     81             "build_info",
     82             "config",
     83             "entropy",
     84             "error",
     85             "lifecycle",
     86             "operations",
     87             "status",
     88             "time",
     89         ])
     90     );
     91     assert!(ROOT.contains("pub use radroots_runtime_paths::{InstanceId, ServiceId};"));
     92     assert!(!STATUS_SOURCE.contains("serde(untagged)"));
     93     assert!(!ADMIN_SOURCE.contains("serde(untagged)"));
     94     for required in [
     95         ".take(REASON_CODES_MAX_ITEMS + 1)",
     96         "deserialize_seq(ReasonCodesVisitor)",
     97         "deserializer.deserialize_str(ReasonCodeVisitor)",
     98     ] {
     99         assert!(STATUS_SOURCE.contains(required));
    100     }
    101     for required in [
    102         "struct NonNullSerializer",
    103         "struct StrictJsonPayload",
    104         "encode_bounded(result, self.response_body_limit)",
    105     ] {
    106         assert!(ADMIN_SOURCE.contains(required));
    107     }
    108     for forbidden in [
    109         "serde_json::Value",
    110         "serde_json::to_value",
    111         "StrictJsonValue",
    112     ] {
    113         assert!(!ADMIN_SOURCE.contains(forbidden));
    114     }
    115     for source in [
    116         CONFIG_DOCUMENT_SOURCE,
    117         CONFIG_VALUE_SOURCE,
    118         ADMIN_SOURCE,
    119         STATUS_SOURCE,
    120         LIFECYCLE_SOURCE,
    121         OPERATIONS_PRIMITIVES_SOURCE,
    122     ] {
    123         for forbidden in [
    124             "impl Into<String>",
    125             "impl Into<Box<str>>",
    126             "let value = value.into();",
    127             "String::deserialize",
    128         ] {
    129             assert!(
    130                 !source.contains(forbidden),
    131                 "bounded text boundary still contains `{forbidden}`"
    132             );
    133         }
    134     }
    135     for forbidden in ["tokio::signal", "ctrl_c", "signal_hook"] {
    136         assert!(!LIFECYCLE_SOURCE.contains(forbidden));
    137     }
    138     for forbidden in ["TcpListener", "TcpStream", "tokio::spawn"] {
    139         assert!(!OPERATIONS_PRIMITIVES_SOURCE.contains(forbidden));
    140     }
    141     assert!(!OPERATIONS_SOURCE.contains("process::exit"));
    142     for source in [CONFIG_DOCUMENT_SOURCE, CONFIG_VALUE_SOURCE] {
    143         let production = source.split_once("#[cfg(test)]").unwrap().0;
    144         for forbidden in [
    145             "create_dir",
    146             "read_dir",
    147             "std::env",
    148             "TcpStream",
    149             "UdpSocket",
    150             "SystemTime",
    151             "MonotonicClock",
    152             "tokio::",
    153             "process::",
    154         ] {
    155             assert!(!production.contains(forbidden));
    156         }
    157     }
    158 }
    159 
    160 #[test]
    161 fn documentation_and_reviewed_public_api_are_complete_and_dependency_safe() {
    162     for required in [
    163         "## Strict configuration values",
    164         "## Cached state and explicit cancellation",
    165         "## Local administration and operations",
    166         "## Process and runtime ownership",
    167         "## Supported targets and publication",
    168         "services_hardening_host.v1.json",
    169         "contracts/api_baselines/radroots_service_host.txt",
    170         "BoundedCount::<64>::new(8)",
    171         "cached_service_state(CachedServiceState::new",
    172         "parent.child_token()",
    173         "streamed directly into the capped response writer",
    174         "validates borrowed UTF-8 before it creates the",
    175         "Administration operation and correlation identifiers are closed ASCII values",
    176         "Their first byte is alphanumeric; later bytes are",
    177         "alphanumeric or `.`, `_`, `:`, or `-`",
    178         "Ordinary `Debug` is redacted and no",
    179         "`Display` implementation exposes the retained value",
    180         "explicit borrowed `as_str` accessor for serialization",
    181         "Shutdown task cancellation is phase aware",
    182         "Entering a phase cancels only tasks",
    183         "assigned to that phase and does not advance until their joins are observed",
    184         "bounded one-shot work drains without",
    185         "cancellation during `DrainOperations`",
    186         "a fatal task outcome still",
    187         "cancels and joins the complete graph",
    188         "retains one absolute",
    189         "deadline plus the completed handler/drain boundary across cancellation and",
    190         "no phase or cleanup attempt receives a fresh grace period",
    191         "incomplete handler may be entered again and must be idempotent and",
    192         "cancellation safe",
    193         "first phase or task failure is retained while later",
    194         "close phases continue as long as the original deadline remains",
    195     ] {
    196         assert!(README.contains(required), "README is missing `{required}`");
    197     }
    198 
    199     for required in [
    200         "pub struct radroots_service_host::BuildInfo",
    201         "pub struct radroots_service_host::ConfigDocumentExpectation",
    202         "pub struct radroots_service_host::PositiveDuration",
    203         "pub struct radroots_service_host::CancellationToken",
    204         "pub struct radroots_service_host::TaskSupervisor",
    205         "pub struct radroots_service_host::AdminRouter",
    206         "pub struct radroots_service_host::OperationsServer",
    207         "pub struct radroots_service_host::BoundedMetricsSnapshot",
    208         "pub struct radroots_service_host::AdminOperationId",
    209         "pub struct radroots_service_host::AdminCorrelationId",
    210         "pub struct radroots_service_host::ServiceStatus",
    211         "pub trait radroots_service_host::MonotonicClock",
    212         "pub trait radroots_service_host::EntropySource",
    213     ] {
    214         assert!(
    215             PUBLIC_API.contains(required),
    216             "reviewed API baseline is missing `{required}`"
    217         );
    218     }
    219 
    220     for forbidden in [
    221         "pub mod radroots_service_host::admin",
    222         "pub mod radroots_service_host::config",
    223         "pub mod radroots_service_host::lifecycle",
    224         "pub mod radroots_service_host::operations",
    225         "pub mod radroots_service_host::status",
    226         "hyper::",
    227         "rustix::",
    228         "serde_json::",
    229         "tokio::",
    230         "tokio_util::",
    231         "impl core::fmt::Display for radroots_service_host::AdminOperationId",
    232         "impl core::fmt::Display for radroots_service_host::AdminCorrelationId",
    233     ] {
    234         assert!(
    235             !PUBLIC_API.contains(forbidden),
    236             "reviewed API baseline exposes `{forbidden}`"
    237         );
    238     }
    239 }
    240 
    241 fn public_modules(root: &str) -> BTreeSet<&str> {
    242     root.lines()
    243         .filter_map(|line| line.strip_prefix("pub mod "))
    244         .filter_map(|module| module.strip_suffix(';'))
    245         .collect()
    246 }
    247 
    248 fn private_modules(root: &str) -> BTreeSet<&str> {
    249     root.lines()
    250         .filter_map(|line| line.strip_prefix("mod "))
    251         .filter_map(|module| module.strip_suffix(';'))
    252         .collect()
    253 }
    254 
    255 fn dependency_keys(manifest: &str) -> BTreeSet<&str> {
    256     manifest
    257         .split_once("[dependencies]")
    258         .map(|(_, dependencies)| dependencies)
    259         .unwrap_or_default()
    260         .lines()
    261         .skip(1)
    262         .take_while(|line| !line.starts_with('['))
    263         .filter_map(|line| line.split_once('=').map(|(key, _)| key.trim()))
    264         .filter(|key| !key.is_empty())
    265         .collect()
    266 }