shakrs-json-parser 0.1.0

Parser, validator, scaffolder, and canonical formatter for the shakrs.json workspace config. Zero I/O; no policy-registry knowledge.
Documentation
//! Canonical serialization + default scaffold for `shakrs.json`.
//!
//! Canonical form is deterministic bytes: keys sorted at every level (the
//! default `serde_json::Value` map is a `BTreeMap`), two-space pretty
//! indentation, and a trailing newline. No Prettier, no Node.

use crate::types::ShakrsConfig;

/// Serialize `config` to canonical `shakrs.json` bytes.
///
/// Round-trips through `serde_json::Value` so object keys come out sorted at
/// every level, then pretty-prints with a trailing newline.
///
/// # Errors
///
/// Returns the `serde_json` serialization error. This cannot occur for these
/// types (string-keyed maps, no erroring `Serialize` impls) but is fallible
/// in the type system.
#[expect(
    clippy::type_complexity,
    reason = "serde_json::Error is the honest serialization-failure type for a JSON crate; aliasing it would hide the error source."
)]
pub fn canonicalize(config: &ShakrsConfig) -> Result<Vec<u8>, serde_json::Error> {
    let value = serde_json::to_value(config)?;
    let mut bytes = serde_json::to_vec_pretty(&value)?;
    bytes.push(b'\n');
    Ok(bytes)
}

/// Canonical bytes of the default `shakrs.json` that `init` writes when the
/// file is absent: `version 1`, every policy enabled by default, no
/// overrides, no waivers.
///
/// # Errors
///
/// Propagates the (practically unreachable) serialization error from
/// [`canonicalize`].
#[expect(
    clippy::type_complexity,
    reason = "Mirrors canonicalize's signature; serde_json::Error is the honest serialization-failure type."
)]
pub fn scaffold_default() -> Result<Vec<u8>, serde_json::Error> {
    canonicalize(&ShakrsConfig::default())
}