lib

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

README (7881B)


      1 # radroots_runtime_paths
      2 
      3 `radroots_runtime_paths` provides canonical, typed runtime paths for Radroots
      4 core libraries. Its public API is exposed only from the crate root. Pure path
      5 resolution never reads the ambient process environment or performs filesystem
      6 I/O. State-directory provisioning is a separate explicit operation.
      7 
      8 ## Overview
      9 
     10 - Validated service and instance identifiers define the sole canonical
     11   `services/<service>/<instance>` namespace.
     12 - Bounded service, instance, and credential artifact names are validated as
     13   borrowed UTF-8 before the crate creates their retained strings; Serde identity
     14   decoding uses the same boundary without a second prevalidation copy.
     15 - Callers inject the platform, host-environment roots, profile, and typed
     16   bootstrap provenance.
     17 - A sealed `RuntimeContext` is the only public service-instance path
     18   construction boundary.
     19 - A sealed state-directory plan validates or provisions only the canonical
     20   `services/<service>/<instance>` suffix under an existing state root.
     21 - Service paths and common artifacts are non-forgeable immutable views.
     22 - Pure shared geonames and runtime-store helpers remain independent of
     23   service-instance path selection.
     24 
     25 The former generic app/service/worker/shared namespace, raw root containers,
     26 path overrides, process-environment selectors, and bootstrap path helpers are
     27 intentionally removed. Callers must construct typed bootstrap provenance and
     28 resolve a `RuntimeContext` from an explicitly injected resolver.
     29 
     30 ## Example
     31 
     32 The following deterministic Linux service-host example resolves one Myc
     33 instance and its common artifacts without consulting or changing the host:
     34 
     35 ```rust
     36 use std::path::Path;
     37 
     38 use radroots_runtime_paths::{
     39     InstanceId, RadrootsHostEnvironment, RadrootsPathProfile,
     40     RadrootsPathResolver, RadrootsPlatform, RuntimeContext,
     41     RuntimeContextBootstrap, RuntimeContextSource, ServiceId,
     42     default_service_instance_artifacts,
     43 };
     44 
     45 let resolver = RadrootsPathResolver::new(
     46     RadrootsPlatform::Linux,
     47     RadrootsHostEnvironment::default(),
     48 );
     49 let bootstrap = RuntimeContextBootstrap::new(
     50     RadrootsPathProfile::ServiceHost,
     51     None,
     52     RuntimeContextSource::SafeDefault,
     53     RuntimeContextSource::BootstrapCli,
     54 )?;
     55 let context = RuntimeContext::resolve(
     56     &resolver,
     57     bootstrap,
     58     ServiceId::new("myc")?,
     59     InstanceId::new("primary")?,
     60 )?;
     61 let artifacts = default_service_instance_artifacts(context.paths());
     62 
     63 assert_eq!(
     64     context.paths().config(),
     65     Path::new("/etc/radroots/services/myc/primary"),
     66 );
     67 assert_eq!(
     68     artifacts.config(),
     69     Path::new("/etc/radroots/services/myc/primary/config.toml"),
     70 );
     71 # Ok::<(), Box<dyn std::error::Error>>(())
     72 ```
     73 
     74 ## Root Profiles
     75 
     76 Every root below receives the suffix `services/<service>/<instance>`. The
     77 service instance's `state` directory is derived from the selected data root.
     78 
     79 | Profile | Config root | Data/state root | Cache root | Logs root | Run root | Secrets root |
     80 | --- | --- | --- | --- | --- | --- | --- |
     81 | Linux `ServiceHost` | `/etc/radroots` | `/var/lib/radroots` | `/var/cache/radroots` | `/var/log/radroots` | `/run/radroots` | `/etc/radroots/secrets` |
     82 | Linux `InteractiveUser` | `$XDG_CONFIG_HOME/radroots` | `$XDG_DATA_HOME/radroots` | `$XDG_CACHE_HOME/radroots` | `$XDG_STATE_HOME/radroots/logs` | `$XDG_RUNTIME_DIR/radroots` | `$XDG_CONFIG_HOME/radroots/secrets` |
     83 | macOS `InteractiveUser` | `$HOME/Library/Application Support/Radroots/config` | `$HOME/Library/Application Support/Radroots/data` | `$HOME/Library/Caches/Radroots` | `$HOME/Library/Logs/Radroots` | `$HOME/Library/Application Support/Radroots/run` | `$HOME/Library/Application Support/Radroots/secrets` |
     84 | Windows `InteractiveUser` | `%APPDATA%\Radroots\config` | `%LOCALAPPDATA%\Radroots\data` | `%LOCALAPPDATA%\Radroots\cache` | `%LOCALAPPDATA%\Radroots\logs` | `%LOCALAPPDATA%\Radroots\run` | `%APPDATA%\Radroots\secrets` |
     85 | `RepoLocal` | `<base>/config` | `<base>/data` | `<base>/cache` | `<base>/logs` | `<base>/run` | `<base>/secrets` |
     86 
     87 Linux XDG inputs must be absolute. Empty, missing, or relative config, data,
     88 state, and cache values use the corresponding absolute `HOME` defaults:
     89 `.config`, `.local/share`, `.local/state`, and `.cache`. An absolute
     90 `XDG_RUNTIME_DIR` is mandatory and has no fallback. Windows interactive
     91 resolution requires both injected `APPDATA` and `LOCALAPPDATA`. Repo-local
     92 resolution requires one explicit absolute, non-root base with no parent
     93 traversal. Repo-local never becomes an implicit or production fallback.
     94 
     95 ## State Directory Provisioning
     96 
     97 `RuntimeContext::state_directory_plan` is pure and performs no filesystem I/O.
     98 Its sealed result exposes no caller-selected path or mutable component. Calling
     99 `RuntimeStateDirectoryPlan::provision` is an explicit filesystem operation.
    100 
    101 For `InteractiveUser` and `RepoLocal`, the canonical data/state root must
    102 already exist, be owned by the effective user, be owner-readable and
    103 owner-searchable, and not be group- or other-writable. The provisioner may then
    104 create only `services/<service>/<instance>`, one descriptor-relative component
    105 at a time, with mode `0700`. It uses no-follow opens, validates every existing
    106 directory, never changes an existing mode, and identity-checks any cleanup of
    107 directories it created during a failed attempt. An entry whose identity cannot
    108 be proven is preserved and the operation fails closed.
    109 
    110 For `ServiceHost`, the entire state-directory suffix must already exist. The
    111 plan performs validation only and never creates or permission-repairs service-
    112 host directories. Provisioning is implemented only on Linux and macOS; other
    113 targets fail with a stable path-free unsupported-platform classification.
    114 
    115 ## Common Artifacts
    116 
    117 | Artifact | Canonical location within the instance |
    118 | --- | --- |
    119 | Configuration | `<config>/config.toml` |
    120 | SQLite state | `<state>/state.sqlite` |
    121 | SQLite writer lock | `<state>/state.lock` |
    122 | Local admin socket | `<run>/admin.sock` |
    123 | Credential artifact | `<secrets>/<validated-credential-name>` |
    124 
    125 The crate derives these paths. Its explicit state-directory provisioner owns
    126 only the narrow behavior described above; it does not create any common
    127 artifact, configuration, cache, log, run, or secrets path. Callers own artifact
    128 creation and its security policy. The shared geonames and runtime-store helpers
    129 are pure joins over caller-supplied roots and do not select or alter a
    130 `RuntimeContext`.
    131 
    132 ## Support Caveats
    133 
    134 Deterministic path behavior is not a qualification claim. Linux service-host
    135 on x86_64 and aarch64 is eligible for Tier 1 only after all release gates pass.
    136 Linux and macOS interactive and explicit repo-local profiles on x86_64 and
    137 aarch64 are developer-target behavior. Linux rootless OCI on x86_64 and
    138 aarch64 is also only a target: it uses the Linux behavior with explicit mounts,
    139 has no separate native path profile, and requires its own qualification gates.
    140 macOS support does not imply launchd packaging, system-wide paths, or Linux
    141 peer-credential equivalence. Windows interactive and repo-local derivation is
    142 implemented but unsupported and carries no v1 support claim.
    143 
    144 Non-Linux `ServiceHost`, `MobileNative`, Android/iOS/Other interactive,
    145 mobile/browser/WASI service use, and every unlisted profile/platform pairing
    146 are unsupported. Successful compilation or path derivation does not change a
    147 target's qualification posture.
    148 
    149 ## Public API Baseline
    150 
    151 The final reviewed root-only API is frozen in the
    152 [runtime-paths API baseline](../../contracts/api_baselines/radroots_runtime_paths.txt)
    153 and checked by the package boundary tests.
    154 
    155 ## Copyright
    156 
    157 Except as otherwise noted, all files in the `radroots_runtime_paths`
    158 distribution are
    159 
    160  Copyright (c) 2025 Tyson Lupul
    161 
    162 For information on usage and redistribution, and for a DISCLAIMER OF ALL
    163 WARRANTIES, see LICENSE included in the `radroots_runtime_paths` distribution.