#![deny(missing_docs)]
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::hash::{BuildHasherDefault, Hasher};
use std::sync::OnceLock;
pub use xuanji::{BoundaryKind, Outcome, Polarity, Report, Severity, Violation};
#[cfg(feature = "audit")]
mod audit;
#[cfg(feature = "audit")]
pub use audit::audit_probe_coverage;
pub const RUNTIME_SEAM_RULE: &str = "only declared origins may cross the seam";
pub trait Tracked: Any {
fn as_any(&self) -> &dyn Any;
}
impl<T: Any> Tracked for T {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Default)]
struct FoldHasher(u64);
impl Hasher for FoldHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
for &b in bytes {
self.0 = self.0.rotate_left(8) ^ b as u64;
}
}
fn write_u64(&mut self, i: u64) {
self.0 ^= i;
}
fn write_u128(&mut self, i: u128) {
self.0 ^= i as u64 ^ (i >> 64) as u64;
}
}
type TidMap<V> = HashMap<TypeId, V, BuildHasherDefault<FoldHasher>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Posture {
Event,
Panic,
}
impl Posture {
pub fn as_str(&self) -> &'static str {
match self {
Posture::Event => "event",
Posture::Panic => "panic",
}
}
}
#[derive(Debug, Clone)]
pub struct RuntimeBoundary {
seam: &'static str,
allowed: Vec<&'static str>,
reason: String,
severity: Severity,
posture: Posture,
anchor: Option<String>,
}
impl RuntimeBoundary {
pub fn at(seam: &'static str) -> RuntimeSeamDraft {
RuntimeSeamDraft { seam }
}
pub fn seam(&self) -> &str {
self.seam
}
pub fn allowed_origins(&self) -> &[&'static str] {
&self.allowed
}
pub fn reason(&self) -> &str {
&self.reason
}
pub fn with_anchor(mut self, anchor: &str) -> Self {
self.anchor = Some(anchor.to_string());
self
}
pub fn anchor(&self) -> Option<&str> {
self.anchor.as_deref()
}
pub fn severity(&self) -> Severity {
self.severity
}
pub fn posture(&self) -> Posture {
self.posture
}
}
pub struct RuntimeSeamDraft {
seam: &'static str,
}
impl RuntimeSeamDraft {
pub fn only_origins<I>(self, origins: I) -> RuntimeBoundaryDraft
where
I: IntoIterator<Item = &'static str>,
{
RuntimeBoundaryDraft {
seam: self.seam,
allowed: origins.into_iter().collect(),
severity: Severity::Enforce,
posture: Posture::Event,
}
}
}
pub struct RuntimeBoundaryDraft {
seam: &'static str,
allowed: Vec<&'static str>,
severity: Severity,
posture: Posture,
}
impl RuntimeBoundaryDraft {
pub fn warn(mut self) -> Self {
self.severity = Severity::Warn;
self
}
pub fn panic_on_violation(mut self) -> Self {
self.posture = Posture::Panic;
self
}
pub fn because(self, reason: &str) -> RuntimeBoundary {
RuntimeBoundary {
seam: self.seam,
allowed: self.allowed,
reason: reason.to_string(),
severity: self.severity,
posture: self.posture,
anchor: None,
}
}
}
#[derive(Debug, Clone)]
pub struct OriginEntry {
type_id: TypeId,
origin: &'static str,
type_name: &'static str,
}
impl OriginEntry {
pub fn new(type_id: TypeId, origin: &'static str, type_name: &'static str) -> Self {
OriginEntry {
type_id,
origin,
type_name,
}
}
}
struct Seam {
allowed: Vec<&'static str>,
reason: String,
severity: Severity,
posture: Posture,
anchor: Option<String>,
}
struct OriginInfo {
origin: &'static str,
type_name: &'static str,
}
struct Registry {
origins: TidMap<OriginInfo>,
seams: HashMap<&'static str, Seam>,
}
static REGISTRY: OnceLock<Registry> = OnceLock::new();
pub fn install<B, O>(boundaries: B, origins: O)
where
B: IntoIterator<Item = RuntimeBoundary>,
O: IntoIterator<Item = OriginEntry>,
{
let mut seams = HashMap::new();
for b in boundaries {
if seams.contains_key(b.seam) {
panic!(
"louke: runtime seam '{}' declared more than once — each seam is declared exactly \
once (a duplicate would silently shadow the earlier boundary)",
b.seam
);
}
seams.insert(
b.seam,
Seam {
allowed: b.allowed,
reason: b.reason,
severity: b.severity,
posture: b.posture,
anchor: b.anchor,
},
);
}
let mut origin_map: TidMap<OriginInfo> = TidMap::default();
for e in origins {
if origin_map.contains_key(&e.type_id) {
panic!(
"louke: an origin for type '{}' was registered more than once — each type \
registers its origin exactly once",
e.type_name
);
}
origin_map.insert(
e.type_id,
OriginInfo {
origin: e.origin,
type_name: e.type_name,
},
);
}
if REGISTRY
.set(Registry {
origins: origin_map,
seams,
})
.is_err()
{
panic!("louke: install called twice — the runtime constitution is write-once");
}
}
fn check_crossing(
seam: &str,
type_id: TypeId,
registry: &Registry,
) -> Result<Option<(Violation, Posture)>, String> {
let s = registry.seams.get(seam).ok_or_else(|| {
format!(
"an undeclared seam is never enforced — declare the RuntimeBoundary or fix the \
probe's seam name: probe references undeclared runtime seam '{seam}'"
)
})?;
let info = registry.origins.get(&type_id);
let origin = info.map(|i| i.origin);
let allowed = match origin {
Some(o) => s.allowed.contains(&o),
None => false,
};
if allowed {
return Ok(None);
}
let finding = match info {
Some(i) => format!("{} ({})", i.origin, i.type_name),
None => format!("<unregistered origin> {type_id:?}"),
};
let rule = format!(
"{RUNTIME_SEAM_RULE} (only origins: {})",
s.allowed.join(", ")
);
Ok(Some((
Violation::new(
BoundaryKind::Runtime,
seam.to_string(),
rule,
finding,
s.reason.clone(),
s.severity,
)
.with_anchor(s.anchor.clone())
.with_polarity(Polarity::AllowlistGap),
s.posture,
)))
}
#[doc(hidden)]
pub fn __react(seam: &'static str, type_id: TypeId) {
let registry = REGISTRY.get().unwrap_or_else(|| {
panic!("louke: assert_boundary!(\"{seam}\", …) ran before louke::install")
});
match check_crossing(seam, type_id, registry) {
Ok(None) => {}
Ok(Some((violation, posture))) => {
emit(&violation);
if posture == Posture::Panic && violation.severity == Severity::Enforce {
panic!(
"louke: runtime boundary '{seam}' violated by {}",
violation.finding
);
}
}
Err(message) => panic!("louke constitution error: {message}"),
}
}
#[allow(clippy::type_complexity)]
static SINK: OnceLock<Box<dyn Fn(&Violation) + Send + Sync>> = OnceLock::new();
pub fn set_sink<F>(sink: F)
where
F: Fn(&Violation) + Send + Sync + 'static,
{
if SINK.set(Box::new(sink)).is_err() {
panic!("louke: set_sink called twice — the sink is set once at startup");
}
}
fn emit(violation: &Violation) {
match SINK.get() {
Some(sink) => sink(violation),
None => eprintln!(
"louke: runtime boundary violated\n{}",
xuanji::pretty_json(&violation.to_json())
),
}
}
#[macro_export]
macro_rules! register_origin {
($ty:ty) => {
$crate::OriginEntry::new(
::std::any::TypeId::of::<$ty>(),
::std::module_path!(),
::std::any::type_name::<$ty>(),
)
};
}
#[macro_export]
macro_rules! assert_boundary {
($seam:expr, $obj:expr) => {
$crate::__react($seam, $crate::Tracked::as_any($obj).type_id())
};
}
#[cfg(test)]
mod tests {
use super::*;
fn registry(
seams: &[(&'static str, &[&'static str], Severity)],
origins: &[(TypeId, &'static str, &'static str)],
) -> Registry {
let mut s = HashMap::new();
for (seam, allowed, severity) in seams {
s.insert(
*seam,
Seam {
allowed: allowed.to_vec(),
reason: "r".to_string(),
severity: *severity,
posture: Posture::Event,
anchor: None,
},
);
}
let mut o: TidMap<OriginInfo> = TidMap::default();
for (tid, origin, name) in origins {
o.insert(
*tid,
OriginInfo {
origin,
type_name: name,
},
);
}
Registry {
origins: o,
seams: s,
}
}
struct Domain;
struct Infra;
#[test]
fn an_allowed_origin_passes() {
let reg = registry(
&[("seam", &["app::domain"], Severity::Enforce)],
&[(TypeId::of::<Domain>(), "app::domain", "Domain")],
);
assert!(
check_crossing("seam", TypeId::of::<Domain>(), ®)
.unwrap()
.is_none()
);
}
#[test]
fn a_disallowed_origin_reacts() {
let reg = registry(
&[("seam", &["app::domain"], Severity::Enforce)],
&[(TypeId::of::<Infra>(), "app::infra", "Infra")],
);
let (v, _posture) = check_crossing("seam", TypeId::of::<Infra>(), ®)
.unwrap()
.unwrap();
assert_eq!(v.kind, BoundaryKind::Runtime);
assert!(v.finding.contains("app::infra"));
assert!(
v.file.is_none(),
"an origin-assertion violation has no source file"
);
assert!(
v.to_json()["file"].is_null(),
"the prod default-sink JSON carries file: null"
);
}
#[test]
fn an_unknown_origin_reacts_fail_closed() {
let reg = registry(&[("seam", &["app::domain"], Severity::Enforce)], &[]);
let (v, _posture) = check_crossing("seam", TypeId::of::<Infra>(), ®)
.unwrap()
.unwrap();
assert!(v.finding.contains("<unregistered origin>"), "{}", v.finding);
}
#[test]
fn distinct_unregistered_types_stay_distinct_findings() {
let reg = registry(&[("seam", &["app::domain"], Severity::Enforce)], &[]);
let a = check_crossing("seam", TypeId::of::<Infra>(), ®)
.unwrap()
.unwrap()
.0;
let b = check_crossing("seam", TypeId::of::<Domain>(), ®)
.unwrap()
.unwrap()
.0;
assert!(a.finding.contains("<unregistered origin>"));
assert!(b.finding.contains("<unregistered origin>"));
assert_ne!(
a.id(),
b.id(),
"distinct unregistered types must have distinct Violation ids: {} vs {}",
a.finding,
b.finding
);
}
#[test]
fn an_undeclared_seam_is_a_constitution_error() {
let reg = registry(&[], &[]);
let err = check_crossing("ghost", TypeId::of::<Domain>(), ®).unwrap_err();
assert!(err.contains("undeclared runtime seam 'ghost'"), "{err}");
}
#[test]
fn the_builder_carries_posture_and_severity() {
let b = RuntimeBoundary::at("s")
.only_origins(["app::domain"])
.panic_on_violation()
.warn()
.because("r");
assert_eq!(b.seam(), "s");
assert_eq!(b.allowed_origins(), &["app::domain"]);
}
#[test]
fn the_fold_hasher_distinguishes_types() {
let mut m: TidMap<u8> = TidMap::default();
m.insert(TypeId::of::<Domain>(), 1);
m.insert(TypeId::of::<Infra>(), 2);
assert_eq!(m.get(&TypeId::of::<Domain>()), Some(&1));
assert_eq!(m.get(&TypeId::of::<Infra>()), Some(&2));
assert_eq!(m.len(), 2);
}
}