Files
tireless/crates/tireless-core/src/policy.rs
rob thijssen c49b531bcd feat(config): load and validate configuration in every binary
The invariants in CLAUDE.md were tested functions nobody called. There was no
config type at all: --config was accepted and ignored by all three binaries,
figment was an unused dependency, and the 124-line config.toml.tmpl was
aspirational. assert_not_anthropic could not run at startup because nothing read
the provider it checks.

Add tireless_core::config, validated on construction so a Config in hand is a
checked one, and tireless_agent::preflight, called by the worker at startup and
by `tireless preflight` on demand — the same function, so the two cannot
disagree. Move the Anthropic guard to tireless_core::policy where validate() can
reach it; tireless_agent::opencode re-exports it so the documented path resolves.

Also make /v1/ready honest. It returned "ok" unconditionally while its own doc
comment promised dependency checks, so the deploy probe greened on a process
that could do nothing. It now reports per-dependency state, with unwired ones
saying not_implemented rather than ok.

Tests parse the shipped template rather than a fixture, so template and code
cannot drift apart silently.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013TxK1CWPkFXqdcXMJ4hVe6
2026-08-07 15:36:25 +03:00

90 lines
3.4 KiB
Rust

//! Constraints that are not ours to relax.
//!
//! Everything in this module encodes a term of service or a safety property
//! rather than a design preference. They live in core, next to the config that
//! carries the values they check, so that there is exactly one place a
//! configuration is admitted — see [`crate::config::Config::validate`].
//!
//! They were previously enforced by whichever binary remembered to call them,
//! which is a way of saying they were not enforced.
use tireless_entities::Error;
/// Provider identifiers that indicate an Anthropic backend.
const ANTHROPIC_MARKERS: &[&str] = &["anthropic", "claude"];
/// Refuse a configuration that points the OpenCode lane at Anthropic.
///
/// OpenCode is a third-party harness with its own provider clients. Driving an
/// Anthropic *subscription* through one is the pattern Anthropic blocked in
/// January 2026, and OpenCode was named explicitly. Anthropic work goes through
/// the Claude Code lane, which spawns the first-party binary and lets it
/// authenticate itself.
///
/// Checked on both the provider id and the base URL, because either can carry
/// the intent. This is a terms-of-service constraint expressed as code: the
/// comment explaining it can rot, a failing startup assertion cannot.
pub fn assert_not_anthropic(provider: &str, base_url: &str) -> Result<(), Error> {
let provider_lc = provider.to_ascii_lowercase();
let url_lc = base_url.to_ascii_lowercase();
// Match provider ids on token boundaries so a self-hosted provider that
// merely *serves* a Claude-compatible surface is not caught by accident,
// while `anthropic`, `anthropic-oauth` and `claude-max` all are.
let provider_hits = ANTHROPIC_MARKERS.iter().any(|m| {
provider_lc
.split(|c: char| !c.is_ascii_alphanumeric())
.any(|part| part == *m)
});
// The URL check is host-based: `api.anthropic.com` is disqualifying wherever
// it appears, but a local gateway is not.
let url_hits = url_lc.contains("anthropic.com");
if provider_hits || url_hits {
return Err(Error::AnthropicViaOpencode(provider.to_string()));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_house_helexa_backend_is_accepted() {
assert!(assert_not_anthropic("lair-helexa", "http://hanzalova.internal:31313/v1").is_ok());
assert!(
assert_not_anthropic("lmstudio", "http://beast.hanzalova.internal:1234/v1").is_ok()
);
}
#[test]
fn anthropic_providers_are_refused() {
for provider in [
"anthropic",
"Anthropic",
"anthropic-oauth",
"claude",
"claude-max",
] {
assert!(
assert_not_anthropic(provider, "http://localhost/v1").is_err(),
"{provider} should be refused"
);
}
}
#[test]
fn the_anthropic_api_host_is_refused_whatever_the_provider_is_called() {
assert!(assert_not_anthropic("totally-fine", "https://api.anthropic.com/v1").is_err());
}
#[test]
fn a_local_gateway_serving_an_anthropic_compatible_surface_is_fine() {
// cortex presents both OpenAI and Anthropic compatible APIs, but it is
// local inference — no Anthropic subscription is involved.
assert!(assert_not_anthropic("lair-helexa", "http://hanzalova.internal:31313/v1").is_ok());
}
}