arcature-cli 2026.2.0

Developer lifecycle CLI for Arcature applications.
Documentation
//! `arc exposure` — list intentionally browser-visible page contracts and lint
//! secret-bearing field names.
//!
//! Reuses the exact Cross-Stack Linker artifact (`arcature-contract` binary
//! output) — there is one metadata source of truth, not a second registry.
//! Never prints prop values or secrets: the contract artifact contains only
//! field names and types, never data. Supports `--json` for CI-friendly
//! machine consumption and exits non-zero when a dangerous field name is
//! found, so a pipeline can fail the build on a lint hit.

use crate::cli::OutputFormat;
use crate::contracts;
use crate::error::CommandError;
use crate::project;
use crate::tool::{HealthReport, HealthStatus};

pub(crate) fn execute(format: OutputFormat) -> Result<(), CommandError> {
    let project = project::discover()?;
    let artifact = contracts::load(&project).map_err(CommandError::Contract)?;
    let mut report = HealthReport::default();
    report.push(
        "registry",
        HealthStatus::Ok,
        format!("{} registered page(s)", artifact.pages.len()),
    );
    for page in artifact.pages.keys() {
        report.push("page", HealthStatus::Ok, page.clone());
    }
    let hits = contracts::dangerous_fields(&artifact.pages);
    for hit in &hits {
        report.push(
            "lint",
            HealthStatus::Error,
            format!(
                "`{}` exposes field `{}` which matches a secret-bearing name",
                hit.page, hit.field
            ),
        );
    }
    match format {
        OutputFormat::Human => report.print_human(),
        OutputFormat::Json => report.print_json()?,
    }
    if report.has_error() {
        Err(CommandError::Unhealthy("exposure"))
    } else {
        Ok(())
    }
}