use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum RoutePolicy {
Requires,
CachePolicy,
Concurrency,
Resilience,
}
impl RoutePolicy {
pub const ALL: [RoutePolicy; 4] = [
RoutePolicy::Requires,
RoutePolicy::CachePolicy,
RoutePolicy::Concurrency,
RoutePolicy::Resilience,
];
pub const fn field(self) -> &'static str {
match self {
RoutePolicy::Requires => "requires",
RoutePolicy::CachePolicy => "cache_policy",
RoutePolicy::Concurrency => "concurrency",
RoutePolicy::Resilience => "resilience",
}
}
pub const fn effect(self) -> &'static str {
match self {
RoutePolicy::Requires => "gate the route behind a resolved session",
RoutePolicy::CachePolicy => "cache the response for the declared ttl/swr",
RoutePolicy::Concurrency => "cap in-flight requests for this route",
RoutePolicy::Resilience => "retry and time-bound the render",
}
}
pub fn parse(field: &str) -> Option<Self> {
Self::ALL.into_iter().find(|p| p.field() == field)
}
pub const fn subfields(self) -> &'static [&'static str] {
match self {
RoutePolicy::CachePolicy => &["ttl", "swr", "negative_ttl", "vary"],
RoutePolicy::Resilience => &["retry", "timeout_ms"],
RoutePolicy::Requires | RoutePolicy::Concurrency => &[],
}
}
pub const fn reserved_subfields(self) -> &'static [&'static str] {
match self {
RoutePolicy::Resilience => &["queue"],
_ => &[],
}
}
}
impl fmt::Display for RoutePolicy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.field())
}
}
pub const STRUCTURAL_FIELDS: [&str; 8] = [
"route",
"mode",
"render_entrypoint",
"source_reads",
"data_inputs",
"prerender",
"placement",
"hydration",
];
#[derive(Debug, Clone)]
pub struct PolicySupport {
tier: String,
enforced: BTreeSet<RoutePolicy>,
delegated: BTreeSet<RoutePolicy>,
}
impl PolicySupport {
pub fn new(tier: impl Into<String>) -> Self {
Self {
tier: tier.into(),
enforced: BTreeSet::new(),
delegated: BTreeSet::new(),
}
}
#[must_use]
pub fn enforces(mut self, policy: RoutePolicy) -> Self {
self.enforced.insert(policy);
self
}
#[must_use]
pub fn delegate(mut self, policy: RoutePolicy) -> Self {
self.delegated.insert(policy);
self
}
pub fn tier(&self) -> &str {
&self.tier
}
pub fn covers(&self, policy: RoutePolicy) -> bool {
self.enforced.contains(&policy) || self.delegated.contains(&policy)
}
pub fn is_delegated(&self, policy: RoutePolicy) -> bool {
self.delegated.contains(&policy)
}
pub fn enforced(&self) -> impl Iterator<Item = RoutePolicy> + '_ {
self.enforced.iter().copied()
}
pub fn delegated(&self) -> impl Iterator<Item = RoutePolicy> + '_ {
self.delegated.iter().copied()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Violation {
Unenforced { route: String, policy: RoutePolicy },
UnknownField { route: String, field: String },
}
impl Violation {
fn route(&self) -> &str {
match self {
Violation::Unenforced { route, .. } | Violation::UnknownField { route, .. } => route,
}
}
fn line(&self) -> String {
match self {
Violation::Unenforced { route, policy } => format!(
" {route} declares `{}` — nothing here will {}",
policy.field(),
policy.effect(),
),
Violation::UnknownField { route, field } => format!(
" {route} declares `{field}`, which nothing in this binary implements — the \
manifest is either newer than this build or uses a slot reserved for one"
),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PolicyRefusal {
pub tier: String,
pub violations: Vec<Violation>,
}
impl fmt::Display for PolicyRefusal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let n = self.violations.len();
write!(
f,
"refusing to start: {n} route policy declaration(s) that `{}` does not enforce.\n",
self.tier,
)?;
for v in &self.violations {
writeln!(f, "{}", v.line())?;
}
let unknown = self
.violations
.iter()
.any(|v| matches!(v, Violation::UnknownField { .. }));
let known: BTreeSet<&'static str> = self
.violations
.iter()
.filter_map(|v| match v {
Violation::Unenforced { policy, .. } => Some(policy.field()),
Violation::UnknownField { .. } => None,
})
.collect();
write!(
f,
"A policy declared here and enforced nowhere is worse than no policy: the route \
serves 200 and looks correct. Either (a) drop the declaration if it was never \
meant to bind, (b) serve these routes on a tier that implements it, or (c) if \
something in front of this process really does enforce it, say so with \
`--policy-delegated <field>` / `MESOFACT_POLICY_DELEGATED=<field,…>`",
)?;
if !known.is_empty() {
write!(
f,
" (here: `{}`)",
known.into_iter().collect::<Vec<_>>().join(",")
)?;
}
f.write_str(".")?;
if unknown {
write!(
f,
" The unknown field(s) are not delegatable — upgrade this binary to one that \
knows them, or rebuild the workload with a matching toolchain."
)?;
}
Ok(())
}
}
impl std::error::Error for PolicyRefusal {}
pub fn check_manifest(raw: &[u8], support: &PolicySupport) -> Result<(), PolicyCheckError> {
let doc: serde_json::Value =
serde_json::from_slice(raw).map_err(|e| PolicyCheckError::Unreadable(e.to_string()))?;
let routes = match doc.get("routes") {
Some(serde_json::Value::Array(routes)) => routes.as_slice(),
Some(_) => return Err(PolicyCheckError::Unreadable("`routes` is not an array".into())),
None => &[],
};
let mut violations = Vec::new();
for route in routes {
let Some(obj) = route.as_object() else {
return Err(PolicyCheckError::Unreadable(
"a manifest route entry is not an object".into(),
));
};
let name = obj
.get("route")
.and_then(|v| v.as_str())
.unwrap_or("<unnamed route>")
.to_string();
for (key, value) in obj {
if STRUCTURAL_FIELDS.contains(&key.as_str()) {
continue;
}
match RoutePolicy::parse(key) {
Some(policy) => {
if is_declared(policy, value) && !support.covers(policy) {
violations.push(Violation::Unenforced {
route: name.clone(),
policy,
});
}
let known = policy.subfields();
if !known.is_empty() {
if let Some(obj) = value.as_object() {
for sub in obj.keys() {
if !known.contains(&sub.as_str()) {
violations.push(Violation::UnknownField {
route: name.clone(),
field: format!("{}.{sub}", policy.field()),
});
}
}
}
}
}
None => violations.push(Violation::UnknownField {
route: name.clone(),
field: key.clone(),
}),
}
}
}
if violations.is_empty() {
return Ok(());
}
violations.sort_by(|a, b| a.route().cmp(b.route()).then_with(|| a.line().cmp(&b.line())));
Err(PolicyCheckError::Refused(PolicyRefusal {
tier: support.tier.clone(),
violations,
}))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PolicyCheckError {
Unreadable(String),
Refused(PolicyRefusal),
}
impl fmt::Display for PolicyCheckError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PolicyCheckError::Unreadable(why) => write!(
f,
"refusing to start: cannot read the route manifest to check for declared \
policy this binary does not enforce — {why}"
),
PolicyCheckError::Refused(r) => r.fmt(f),
}
}
}
impl std::error::Error for PolicyCheckError {}
fn is_declared(policy: RoutePolicy, value: &serde_json::Value) -> bool {
if value.is_null() {
return false;
}
match policy {
RoutePolicy::Requires => value.as_array().is_some_and(|a| !a.is_empty()),
RoutePolicy::CachePolicy => {
let Some(obj) = value.as_object() else {
return true;
};
obj.get("ttl").and_then(|v| v.as_u64()).unwrap_or(0) > 0
|| obj.contains_key("swr")
|| obj.contains_key("negative_ttl")
|| obj
.get("vary")
.is_some_and(|v| v.as_array().is_some_and(|a| !a.is_empty()))
}
RoutePolicy::Concurrency => true,
RoutePolicy::Resilience => value
.as_object()
.is_some_and(|o| o.values().any(|v| !v.is_null())),
}
}
pub fn by_policy(refusal: &PolicyRefusal) -> BTreeMap<&'static str, Vec<&str>> {
let mut out: BTreeMap<&'static str, Vec<&str>> = BTreeMap::new();
for v in &refusal.violations {
let key = match v {
Violation::Unenforced { policy, .. } => policy.field(),
Violation::UnknownField { .. } => "<unknown>",
};
out.entry(key).or_default().push(v.route());
}
out
}
#[cfg(test)]
mod tests {
use super::*;
use crate::manifest::{
CachePolicy, Hydration, Prerender, Requires, ResiliencePolicy, ResolvedPlacement,
RetryPolicy, Route, RouteMode,
};
fn serve_tier() -> PolicySupport {
PolicySupport::new("mesofact serve").enforces(RoutePolicy::Resilience)
}
fn manifest(routes: &str) -> Vec<u8> {
format!(r#"{{"version":"1","build_id":"b","routes":[{routes}]}}"#).into_bytes()
}
const PLAIN: &str = r#"{"route":"/","mode":"static","render_entrypoint":"e.js","cache_policy":{"ttl":0}}"#;
#[test]
fn a_declared_unenforced_policy_has_no_success_path() {
let tier = serve_tier();
let declarations = [
r#""requires":["user"]"#,
r#""cache_policy":{"ttl":3600}"#,
r#""cache_policy":{"ttl":0,"swr":60}"#,
r#""cache_policy":{"ttl":0,"vary":["accept-language"]}"#,
r#""concurrency":4"#,
r#""future_policy":{"limit":2}"#,
];
for decl in declarations {
let raw = manifest(&format!(
r#"{{"route":"/p","mode":"ssr","render_entrypoint":"e.js","cache_policy":{{"ttl":0}},{decl}}}"#
));
match check_manifest(&raw, &tier) {
Err(PolicyCheckError::Refused(_)) => {}
other => panic!(
"declaring {decl} on a tier that does not enforce it returned {other:?}; \
that is the silent no-op R749-T1 forbids ({} policies known)",
RoutePolicy::ALL.len(),
),
}
}
}
#[test]
fn the_refusal_names_the_route_and_the_field() {
let raw = manifest(
r#"{"route":"/private","mode":"ssr","render_entrypoint":"e.js","cache_policy":{"ttl":0},"requires":["user"]}"#,
);
let err = check_manifest(&raw, &serve_tier()).unwrap_err().to_string();
assert!(err.contains("/private"), "{err}");
assert!(err.contains("requires"), "{err}");
assert!(err.contains("--policy-delegated"), "{err}");
}
#[test]
fn the_inert_cache_policy_every_route_carries_is_not_a_declaration() {
assert!(check_manifest(&manifest(PLAIN), &serve_tier()).is_ok());
}
#[test]
fn an_enforced_policy_passes_and_a_delegated_one_does_too() {
let raw = manifest(
r#"{"route":"/a","mode":"ssr","render_entrypoint":"e.js","cache_policy":{"ttl":0},"resilience":{"timeout_ms":5000},"requires":["user"]}"#,
);
assert!(check_manifest(&raw, &serve_tier()).is_err());
let trusting = serve_tier().delegate(RoutePolicy::Requires);
assert!(check_manifest(&raw, &trusting).is_ok());
assert!(trusting.is_delegated(RoutePolicy::Requires));
assert!(!trusting.is_delegated(RoutePolicy::Resilience));
}
#[test]
fn an_empty_policy_block_is_not_a_declaration() {
let raw = manifest(
r#"{"route":"/a","mode":"ssr","render_entrypoint":"e.js","cache_policy":{"ttl":0},"resilience":{},"requires":[]}"#,
);
assert!(check_manifest(&raw, &PolicySupport::new("bare")).is_ok());
}
#[test]
fn an_unparseable_manifest_is_not_a_pass() {
assert!(matches!(
check_manifest(b"{ not json", &serve_tier()),
Err(PolicyCheckError::Unreadable(_))
));
assert!(matches!(
check_manifest(br#"{"routes":"nope"}"#, &serve_tier()),
Err(PolicyCheckError::Unreadable(_))
));
}
#[test]
fn an_unknown_field_is_refused_and_not_delegatable() {
let raw = manifest(
r#"{"route":"/x","mode":"ssr","render_entrypoint":"e.js","cache_policy":{"ttl":0},"rate_limit":{"rps":10}}"#,
);
let mut permissive = serve_tier();
for p in RoutePolicy::ALL {
permissive = permissive.delegate(p);
}
let err = check_manifest(&raw, &permissive).unwrap_err().to_string();
assert!(err.contains("rate_limit"), "{err}");
assert!(err.contains("not delegatable"), "{err}");
}
#[test]
fn every_route_field_is_classified() {
let full = Route {
route: "/x/:id".into(),
mode: RouteMode::Ssr,
render_entrypoint: "dist/server/x.js".into(),
requires: Some(vec![Requires::User]),
source_reads: Some(vec!["s".into()]),
data_inputs: Some(vec!["d.json".into()]),
cache_policy: CachePolicy {
ttl: 1,
swr: Some(1),
negative_ttl: Some(1),
vary: Some(vec!["accept".into()]),
},
concurrency: Some(1),
hydration: Some(Hydration {
script: "s.js".into(),
code_split: vec![],
}),
prerender: Some(Prerender::Deferred { deferred: true }),
placement: Some(ResolvedPlacement::Host),
resilience: Some(ResiliencePolicy {
retry: Some(RetryPolicy {
attempts: 2,
backoff_ms: vec![10],
retry_on: None,
budget_ms: None,
}),
queue: None,
timeout_ms: Some(1),
}),
};
let json = serde_json::to_value(&full).unwrap();
let unclassified: Vec<&String> = json
.as_object()
.unwrap()
.keys()
.filter(|k| {
!STRUCTURAL_FIELDS.contains(&k.as_str()) && RoutePolicy::parse(k).is_none()
})
.collect();
assert!(
unclassified.is_empty(),
"manifest Route gained field(s) {unclassified:?} that are neither a RoutePolicy nor \
STRUCTURAL_FIELDS. Decide which: if a serving tier ignoring it would silently drop \
behaviour an author asked for, it is a RoutePolicy and every tier must advertise \
it; otherwise add it to STRUCTURAL_FIELDS with a reason.",
);
for policy in RoutePolicy::ALL {
let value = json
.get(policy.field())
.unwrap_or_else(|| panic!(
"RoutePolicy::{policy:?} names `{}`, which is not a field on manifest::Route",
policy.field(),
));
let Some(obj) = value.as_object() else { continue };
let unclassified: Vec<&String> = obj
.keys()
.filter(|k| {
!policy.subfields().contains(&k.as_str())
&& !policy.reserved_subfields().contains(&k.as_str())
})
.collect();
assert!(
unclassified.is_empty(),
"`{}` gained sub-field(s) {unclassified:?}: add them to RoutePolicy::subfields \
once a tier implements them, or to reserved_subfields with the doc that \
reserves the slot",
policy.field(),
);
}
}
#[test]
fn a_reserved_subfield_refuses_even_where_its_parent_policy_is_enforced() {
let raw = manifest(
r#"{"route":"/q","mode":"ssr","render_entrypoint":"e.js","cache_policy":{"ttl":0},"resilience":{"timeout_ms":100,"queue":{"queue":"q","ack":"on_enqueue"}}}"#,
);
let err = check_manifest(&raw, &serve_tier()).unwrap_err().to_string();
assert!(err.contains("resilience.queue"), "{err}");
}
#[test]
fn an_unknown_cache_directive_refuses_instead_of_being_dropped_by_serde() {
let raw = manifest(
r#"{"route":"/c","mode":"static","render_entrypoint":"e.js","cache_policy":{"ttl":60,"shared_max_age":30}}"#,
);
let tier = serve_tier().enforces(RoutePolicy::CachePolicy);
let err = check_manifest(&raw, &tier).unwrap_err().to_string();
assert!(err.contains("cache_policy.shared_max_age"), "{err}");
}
}