pithy-core 0.0.2

UltraCoS® symbolic token compression — 17-rule encoder for LLM prompts. PolyForm Noncommercial.
Documentation
//! Single source of truth for product branding.
//!
//! Every product-name string that appears in filesystem paths, environment
//! variables, launchd bundle identifiers, socket paths, binary names, or
//! attribution strings derives from the constants in this module.
//!
//! Renaming the product reduces to changing the constants below plus running
//! the Cargo/launchd/data-dir migration documented in `docs/BRANDING.md`.
//!
//! # Backward compatibility during rename
//!
//! The [`read_env`] helper tries the current prefix first and falls back to
//! the historical `ULTRACOS_` prefix, so env vars set by old launchd plists
//! keep working across a partial rollout.

use std::path::PathBuf;

// ─── Brand constants (SSOT) ───────────────────────────────────────────────────

/// Lowercase product name. Used in filesystem paths, Cargo crate prefix,
/// binary names, socket stems, and CLI identifiers.
///
/// Example uses: `~/.pithy/`, `/tmp/pithy.sock`, `pithy-shim` binary.
pub const PRODUCT_NAME: &str = "pithy";

/// Display-cased brand name. Used in prose, log prefixes, docs, attribution.
///
/// Must match the `PRODUCT_NAME` except for casing (validated by test).
pub const PRODUCT_BRAND: &str = "Pithy";

/// Uppercase prefix for environment variables.
///
/// Example: `PITHY_SHADOW_RATE`, `PITHY_EMBEDDER_SOCKET`.
pub const ENV_PREFIX: &str = "PITHY";

/// Launchd bundle-identifier namespace (reverse-DNS).
///
/// Full bundle IDs combine this with a component: `com.pithy.shim`,
/// `com.pithy.controller`, `com.pithy.embedder`.
pub const BUNDLE_NS: &str = "com.pithy";

/// Config/data directory name under `$HOME`. Dot-prefixed.
///
/// Example: `~/.pithy/` holds `audit.jsonl`, `shadow.jsonl`,
/// `rules.toml`, `snapshot.json`, sockets, and PID files.
pub const CONFIG_DIR_NAME: &str = ".pithy";

/// Public repository URL. Embedded in attribution strings.
pub const REPO_URL: &str = "https://github.com/MikkoParkkola/pithy";

/// Compile-time attribution string, unremovable in release builds.
///
/// Required by `LICENSE-ATTRIBUTION.md` for all derivatives. Validated at
/// test time to contain [`PRODUCT_BRAND`] and [`REPO_URL`] so renames
/// cannot leave the attribution desynchronised.
pub const ATTRIBUTION: &str = "Powered by Pithy(R) - https://github.com/MikkoParkkola/pithy";

// ─── Derived helpers ──────────────────────────────────────────────────────────

/// Build a full environment-variable name by joining [`ENV_PREFIX`] with
/// `suffix` using `_`.
///
/// # Examples
/// ```
/// use pithy_core::branding::env_var_name;
/// assert_eq!(env_var_name("SHADOW_RATE"), "PITHY_SHADOW_RATE");
/// ```
#[must_use]
pub fn env_var_name(suffix: &str) -> String {
    format!("{ENV_PREFIX}_{suffix}")
}

/// Build the config-directory absolute path under the user's `$HOME`.
///
/// Falls back to `/tmp/<CONFIG_DIR_NAME>` when `HOME` is unset (rare; mostly
/// minimal container environments) so callers never receive a panic.
#[must_use]
pub fn config_dir() -> PathBuf {
    std::env::var_os("HOME")
        .map(PathBuf::from)
        .unwrap_or_else(|| PathBuf::from("/tmp"))
        .join(CONFIG_DIR_NAME)
}

/// Build a Unix-socket path under `/tmp/` using the product-name stem.
///
/// # Examples
/// ```
/// use pithy_core::branding::socket_path;
/// let p = socket_path("shim");
/// assert_eq!(p.to_string_lossy(), "/tmp/pithy-shim.sock");
/// ```
#[must_use]
pub fn socket_path(name: &str) -> PathBuf {
    PathBuf::from("/tmp").join(format!("{PRODUCT_NAME}-{name}.sock"))
}

/// Build a JSONL log-file path under `/tmp/` using the product-name stem.
///
/// # Examples
/// ```
/// use pithy_core::branding::log_path;
/// let p = log_path("shadow");
/// assert_eq!(p.to_string_lossy(), "/tmp/pithy-shadow.jsonl");
/// ```
#[must_use]
pub fn log_path(name: &str) -> PathBuf {
    PathBuf::from("/tmp").join(format!("{PRODUCT_NAME}-{name}.jsonl"))
}

/// Compose a full launchd bundle identifier from the namespace and a
/// component name.
///
/// # Examples
/// ```
/// use pithy_core::branding::bundle_id;
/// assert_eq!(bundle_id("shim"), "com.pithy.shim");
/// ```
#[must_use]
pub fn bundle_id(component: &str) -> String {
    format!("{BUNDLE_NS}.{component}")
}

/// Read an environment variable by its suffix, trying current prefix first
/// and falling back to the legacy `ULTRACOS_` prefix.
///
/// This lets a rollout flip [`ENV_PREFIX`] to a new value while old launchd
/// plists still export variables under the legacy prefix — neither callsite
/// nor daemon needs a code change during the transition window.
///
/// Returns `None` when neither variable is set or when the value is not
/// valid Unicode.
#[must_use]
pub fn read_env(suffix: &str) -> Option<String> {
    std::env::var(env_var_name(suffix))
        .ok()
        .or_else(|| std::env::var(format!("ULTRACOS_{suffix}")).ok())
}

// ─── Tests ────────────────────────────────────────────────────────────────────

#[cfg(test)]
mod tests {
    use super::*;

    // GIVEN: brand constants
    // WHEN:  compared case-insensitively
    // THEN:  lowercase form matches uppercase form
    #[test]
    fn product_name_and_brand_agree_case_insensitive() {
        assert_eq!(
            PRODUCT_NAME.to_ascii_uppercase(),
            PRODUCT_BRAND.to_ascii_uppercase(),
            "PRODUCT_NAME={PRODUCT_NAME} and PRODUCT_BRAND={PRODUCT_BRAND} \
             must differ only in casing; did a rename leave one behind?"
        );
    }

    #[test]
    fn env_prefix_matches_product_name_uppercase() {
        assert_eq!(
            ENV_PREFIX,
            PRODUCT_NAME.to_ascii_uppercase(),
            "ENV_PREFIX must be the uppercase form of PRODUCT_NAME"
        );
    }

    #[test]
    fn bundle_ns_uses_product_name() {
        assert!(
            BUNDLE_NS.ends_with(PRODUCT_NAME),
            "BUNDLE_NS={BUNDLE_NS} must end with PRODUCT_NAME={PRODUCT_NAME}"
        );
    }

    #[test]
    fn config_dir_name_uses_product_name() {
        assert_eq!(
            CONFIG_DIR_NAME,
            format!(".{PRODUCT_NAME}"),
            "CONFIG_DIR_NAME must be the dot-prefixed PRODUCT_NAME"
        );
    }

    #[test]
    fn attribution_contains_brand() {
        assert!(
            ATTRIBUTION.contains(PRODUCT_BRAND),
            "ATTRIBUTION must reference PRODUCT_BRAND={PRODUCT_BRAND}; \
             got: {ATTRIBUTION}"
        );
    }

    #[test]
    fn attribution_contains_repo_url() {
        assert!(
            ATTRIBUTION.contains(REPO_URL),
            "ATTRIBUTION must reference REPO_URL; got: {ATTRIBUTION}"
        );
    }

    #[test]
    fn env_var_name_joins_with_underscore() {
        assert_eq!(
            env_var_name("SHADOW_RATE"),
            format!("{ENV_PREFIX}_SHADOW_RATE")
        );
        assert_eq!(env_var_name("BYPASS"), format!("{ENV_PREFIX}_BYPASS"));
    }

    #[test]
    fn socket_path_uses_product_stem() {
        let p = socket_path("shim");
        assert_eq!(
            p.to_string_lossy(),
            format!("/tmp/{PRODUCT_NAME}-shim.sock")
        );
    }

    #[test]
    fn log_path_uses_product_stem() {
        let p = log_path("shadow");
        assert_eq!(
            p.to_string_lossy(),
            format!("/tmp/{PRODUCT_NAME}-shadow.jsonl")
        );
    }

    #[test]
    fn bundle_id_composes_from_ns_and_component() {
        assert_eq!(bundle_id("shim"), format!("{BUNDLE_NS}.shim"));
        assert_eq!(bundle_id("controller"), format!("{BUNDLE_NS}.controller"));
        assert_eq!(bundle_id("embedder"), format!("{BUNDLE_NS}.embedder"));
    }

    // GIVEN: HOME is set to a known path
    // WHEN:  config_dir is called
    // THEN:  result is $HOME/<CONFIG_DIR_NAME>
    #[test]
    fn config_dir_joins_home_with_config_dir_name() {
        std::env::set_var("HOME", "/tmp/branding-test-home");
        let p = config_dir();
        assert_eq!(
            p.to_string_lossy(),
            format!("/tmp/branding-test-home/{CONFIG_DIR_NAME}")
        );
    }

    // GIVEN: an env var is set under the legacy ULTRACOS_ prefix, and the
    //        current-prefix form is absent
    // WHEN:  read_env is called with that suffix
    // THEN:  the value is returned (fallback path exercised when current
    //        prefix differs; coincident path exercised while ENV_PREFIX is
    //        still "ULTRACOS")
    #[test]
    fn read_env_falls_back_to_legacy_ultracos_prefix() {
        let suffix = "BRANDING_LEGACY_FALLBACK_TEST";
        let legacy_key = format!("ULTRACOS_{suffix}");
        let current_key = env_var_name(suffix);
        // Start clean. Both removals in case siblings left state.
        std::env::remove_var(&legacy_key);
        std::env::remove_var(&current_key);
        // Set only the legacy form.
        std::env::set_var(&legacy_key, "legacy-hit");

        let got = read_env(suffix);

        // Clean up before assertion so a panic does not leak env state.
        std::env::remove_var(&legacy_key);
        std::env::remove_var(&current_key);
        assert_eq!(got.as_deref(), Some("legacy-hit"));
    }

    #[test]
    fn read_env_returns_none_when_unset() {
        let key = "BRANDING_DEFINITELY_NOT_SET_XYZ";
        std::env::remove_var(env_var_name(key));
        std::env::remove_var(format!("ULTRACOS_{key}"));
        assert_eq!(read_env(key), None);
    }
}