This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 11:15:58 +02:00
1 parent 87e571c170
commit fa7abc9e53
308 files changed
+49746 -50237

No files matched your search

+118 -107
View File
@@ -8,15 +8,23 @@ import sqlite3
import subprocess
import tomllib
from preflight import check as preflight
from rust_source import rust_source
from web_assets import read_app_js, read_vhosts_js
root = Path(__file__).resolve().parents[1]
def read_cache_source() -> str:
return "\n".join(path.read_text() for path in sorted((root / "src/cache").glob("*.rs")))
return rust_source(root, "src/cache/mod.rs")
def read_deploy_source() -> str:
return "\n".join((root / name).read_text(encoding="utf-8") for name in ("scripts/deploy_core.py", "scripts/deploy_runtime.py", "scripts/deploy.py"))
def read_docker_agent_source() -> str:
return "\n".join(path.read_text(encoding="utf-8") for path in sorted((root / "docker-agent").glob("*.go")) if not path.name.endswith("_test.go"))
preflight(root)
manifest = tomllib.loads((root / "Cargo.toml").read_text())
assert manifest["package"]["version"] == "0.25.0"
assert manifest["package"]["version"] == "0.25.1"
assert manifest["dependencies"]["quinn"]["version"] == "0.11.12"
h3dep = manifest["dependencies"]["h3"]
assert h3dep["package"] == "hpx-h3" and h3dep["version"] == "=2.5.19" and "quinn" in h3dep["features"]
@@ -24,14 +32,14 @@ assert "h3-quinn" not in manifest["dependencies"]
lock_path = root / "Cargo.lock"
if lock_path.exists():
lock = lock_path.read_text()
assert 'name = "rust-proxy"\nversion = "0.25.0"' in lock
assert 'name = "rust-proxy"\nversion = "0.25.1"' in lock
assert 'name = "systemstat"' in lock and 'name = "metrics-process"' in lock and 'name = "sysinfo"' in lock, "Cargo.lock must be resolver-generated after adding cross-platform statistics libraries"
for release_doc, marker in {
"README.md": "# RustProxy 0.25.0",
"CHANGELOG.md": "## 0.25.0",
"ROADMAP.md": "## 0.25.0",
"AGENTS.md": "Current source version: 0.25.0.",
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.25.0",
"README.md": "# RustProxy 0.25.1",
"CHANGELOG.md": "## 0.25.1",
"ROADMAP.md": "## 0.25.1",
"AGENTS.md": "Current source version: 0.25.1.",
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.25.1",
}.items():
assert marker in (root / release_doc).read_text(), f"stale release identity in {release_doc}"
assert tomllib.loads((root / "rust-toolchain.toml").read_text())["toolchain"]["channel"] == "stable"
@@ -41,7 +49,7 @@ assert update_defaults == {
"version_url": "https://git.linuxiarz.pl/gru/RustProxy/raw/branch/master/Cargo.toml",
"interval_seconds": 3600,
}
update_check_source = (root / "src/update_check.rs").read_text()
update_check_source = rust_source(root, "src/update_check.rs")
for marker in [
'include_str!("../UPDATE_CHECK.toml")',
'pub async fn poll_loop',
@@ -82,7 +90,7 @@ for path in (root / "src").rglob("*.rs"):
for index in range(len(lines) - 1):
assert not (lines[index].lstrip().startswith("#[derive(") and lines[index + 1].lstrip().startswith("#[derive(")), f"consecutive derive attributes in {path}:{index + 1}"
html = (root / "src/admin/web/index.html").read_text()
js = "\n".join(p.read_text() for p in (root / "src/admin/web").glob("*.js") if p.name not in ("login.js", "docs.js"))
js = "\n".join(p.read_text() for p in (root / "src/admin/web").rglob("*.js") if p.name not in ("login.js", "docs.js"))
ids = re.findall(r'id="([^"]+)"', html)
assert len(ids) == len(set(ids)), "duplicate HTML IDs"
for identifier in set(re.findall(r'\$\("([^"]+)"\)', js)):
@@ -112,10 +120,12 @@ unit = (root / "deploy/rustproxy.service").read_text()
assert "LogsDirectory=rustproxy" in unit and "/var/log/rustproxy" in unit
assert "Environment=MALLOC_ARENA_MAX=2" in unit
assert "Environment=MALLOC_ARENA_MAX=2" in (root / "debian/rustproxy.service").read_text()
assert "Environment=MALLOC_ARENA_MAX=2" in (root / "scripts/deploy.py").read_text()
assert "Environment=MALLOC_ARENA_MAX=2" in read_deploy_source()
assert not re.search(r"\b20\d{2}[-/]\d{1,2}[-/]\d{1,2}\b", (root / "CHANGELOG.md").read_text()), "changelog contains a release date"
subprocess.run(["python3", str(root / "scripts/langs_check.py")], check=True)
subprocess.run(["python3", str(root / "scripts/web_server_contracts.py")], check=True)
subprocess.run(["python3", str(root / "scripts/rust_module_contracts.py")], check=True)
subprocess.run(["python3", str(root / "scripts/source_module_contracts.py")], check=True)
dockerfile = (root / "Dockerfile").read_text()
assert "cargo generate-lockfile" in dockerfile and "cargo build --locked --release" in dockerfile
assert "USER rustproxy:rustproxy" in dockerfile
@@ -131,8 +141,9 @@ assert 'data-panel="docker-vhosts"' in html and 'id="panel-docker-vhosts"' in ht
assert 'id="settings-tab-docker-agents"' in html and 'id="settings-page-docker-agents"' in html
assert '/assets/docker.js' in html and 'cache-live-toggle' in html
assert 'expose-revision' not in html and 'hideRevision' not in js and 'diagRevision' not in js
for path in ['src/settings.rs', 'src/admin/mod.rs', 'src/cache/mod.rs', 'src/headers.rs', 'src/tinyauth.rs', 'src/admin/web/vhosts.js']:
assert 'x-rust-proxy-revision' not in (root / path).read_text().lower(), f'legacy revision-header logic remains in {path}'
for path in ['src/settings.rs', 'src/admin/mod.rs', 'src/cache/mod.rs', 'src/headers.rs', 'src/tinyauth.rs', 'src/admin/web/vhosts/core.js']:
text = rust_source(root, path) if path.endswith('.rs') else (root / path).read_text()
assert 'x-rust-proxy-revision' not in text.lower(), f'legacy revision-header logic remains in {path}'
assert './dev.sh admin reset-password' not in html and re.search(r'rust-proxy\s+admin reset-password locally', html)
assert 'data-panel="redirects"' in html and 'id="panel-redirects"' in html
assert 'data-panel="configuration"' not in html and 'id="panel-configuration"' not in html
@@ -140,7 +151,7 @@ assert 'id="settings-tab-manual-config"' in html and 'id="settings-page-manual-c
assert 'id="security-audit-open"' in html and 'id="audit-dialog"' in html and 'id="audit-dialog-close"' in html
assert 'id="security-password-editor"' in html and 'id="security-policy-editor"' in html
assert 'docker-service-editor' in (root / "src/admin/web/docker.js").read_text() and 'docker-agent-details' in (root / "src/admin/web/docker.js").read_text()
balance_source = (root / "src/balance.rs").read_text()
balance_source = rust_source(root, "src/balance.rs")
assert 'mode: HealthMode::Tcp' in balance_source
for marker in [
'pub struct PassiveHealth', 'enabled: false', 'pub passive_health: PassiveHealth',
@@ -160,7 +171,7 @@ assert html.index('data-panel="vhosts"') < html.index('data-panel="redirects"')
assert 'id="stream-dialog"' in html and 'id="stream-list"' in html and 'id="stream-search"' in html
assert 'id="settings-page-streams"' not in html and 'id="streams-form"' not in html
assert '/assets/streams.js' in html and '/assets/redirects.js' in html and '/assets/host404.js' in html
vhosts_js = (root / "src/admin/web/vhosts.js").read_text()
vhosts_js = read_vhosts_js(root)
assert '"force-ssl", "vhForceSsl"' in vhosts_js and 'force_ssl: yes("force-ssl")' in vhosts_js
assert 'vhForceSslNeedsHttp' in vhosts_js and 'tlsPorts.has(443)' in vhosts_js
assert '"forward-client-ip", "vhForwardClientIp"' in vhosts_js and 'forward_client_ip: yes("forward-client-ip")' in vhosts_js
@@ -182,10 +193,10 @@ docker_js = (root / "src/admin/web/docker.js").read_text()
assert 'preserve.checked = assignment?.preserve_host !== false' in docker_js, "new Docker backends must preserve public Host by default"
for marker in ['saveSection("docker-agents"', '/api/docker/refresh', 'docker-publish', 'docker-hostname', 'host-chip-editor docker-alias-editor', 'docker-target-ip', 'default_target_ip', 'docker-agent-fingerprint', 'docker-agent-certificate', 'docker-health-mode', 'docker-passive-enabled', 'docker-passive-5xx', 'docker-search', 'docker-show-hidden', 'dockerHideVhost', 'pool_routes', 'setInterval']:
assert marker in docker_js, marker
docker_source = (root / "src/docker.rs").read_text()
docker_source = rust_source(root, "src/docker.rs")
for marker in ['pub struct Settings', 'pub struct Observation', 'pub struct HostAddress', 'pub struct Binding', 'aliases: Vec<String>', 'target_ip: Option<IpAddr>', 'tls_fingerprint_sha256', 'certificate_id: Option<String>', 'health_check: crate::balance::HealthCheck', 'passive_health: crate::balance::PassiveHealth', 'PinnedCertificateVerifier', 'fingerprint mismatch', 'effective_config', 'poll_loop', 'address_allowlist']:
assert marker in docker_source, marker
agent_source = (root / "docker-agent/main.go").read_text()
agent_source = read_docker_agent_source()
for marker in ['/v1/inventory', 'Authorization', '/containers/json?all=0', 'IsLoopback', 'localHostAddresses', 'detectedAddresses', 'Bindings', 'RUSTPROXY_DOCKER_AGENT_TOKEN', 'ensureSelfSignedCertificate', 'ListenAndServeTLS', 'RUSTPROXY_DOCKER_AGENT_TLS', 'CertificateSHA256']:
assert marker in agent_source, marker
assert 'pool-vhost-disabled' in vhosts_js and '.pool-vhost-disabled' in css
@@ -213,7 +224,7 @@ assert 'Opt-in health decisions based on ordinary user traffic. Defaults to disa
assert '"force_ssl"' in openapi and '"forward_client_ip"' in openapi
assert '"backend_header"' in openapi and '"backend_timing_header"' in openapi
assert '"StreamMetrics"' in openapi and '"streams"' in openapi
for marker in ['"version": "0.25.0"', '"/api/traffic"', '"capture_user_agent"', '"capture_country"', '"hot_auto_trim_enabled"', '"hot_auto_trim_after_seconds"', '"hot_auto_trim_target_percent"', '"/api/config/{section}"', '"ConfigSectionUpdate"', '"cold_on_idle"', '"cold_on_age"', '"cold_max_hot_seconds"', '"cold_on_lru"', '"cold_on_shutdown"', '"cold_gc_interval_seconds"', '"cold_gc_max_delete"', '"collapse_enabled"', '"collapse_wait_timeout_ms"', '"collapse_timeout_fallback"', '"stale_if_error_timeout"', '"stale_if_error_connection"', '"stale_if_error_dns"', '"stale_if_error_tls"', '"stale_if_error_statuses"', '"proactive_refresh_enabled"', '"proactive_refresh_before_expiry_seconds"', '"proactive_refresh_percent"', '"proactive_refresh_max_inflight"', '"TransformSettings"', '"TransformOverrides"', '"/api/cache/cold/cleanup"', '"/api/cache/invalidate"', '"/api/cache/bans"', '"/api/cache/bans/{id}"', '"CacheInvalidationRequest"', '"CacheInvalidationResponse"', '"ColdCleanupJob"', '"match_type"', '"regex_insensitive"', '"rewrite"', '"response"', '"covered_hosts"', '"default": true']:
for marker in ['"version": "0.25.1"', '"/api/traffic"', '"capture_user_agent"', '"capture_country"', '"hot_auto_trim_enabled"', '"hot_auto_trim_after_seconds"', '"hot_auto_trim_target_percent"', '"/api/config/{section}"', '"ConfigSectionUpdate"', '"cold_on_idle"', '"cold_on_age"', '"cold_max_hot_seconds"', '"cold_on_lru"', '"cold_on_shutdown"', '"cold_gc_interval_seconds"', '"cold_gc_max_delete"', '"collapse_enabled"', '"collapse_wait_timeout_ms"', '"collapse_timeout_fallback"', '"stale_if_error_timeout"', '"stale_if_error_connection"', '"stale_if_error_dns"', '"stale_if_error_tls"', '"stale_if_error_statuses"', '"proactive_refresh_enabled"', '"proactive_refresh_before_expiry_seconds"', '"proactive_refresh_percent"', '"proactive_refresh_max_inflight"', '"TransformSettings"', '"TransformOverrides"', '"/api/cache/cold/cleanup"', '"/api/cache/invalidate"', '"/api/cache/bans"', '"/api/cache/bans/{id}"', '"CacheInvalidationRequest"', '"CacheInvalidationResponse"', '"ColdCleanupJob"', '"match_type"', '"regex_insensitive"', '"rewrite"', '"response"', '"covered_hosts"', '"default": true']:
assert marker in openapi, marker
for marker in ['"NotFoundHost"', '"not_found_hosts"', '"PrometheusSettings"', '"allow_trusted_network_without_token"', '"include_docker_vhosts"', '"include_streams"', '"include_logging"']:
assert marker in openapi, marker
@@ -233,17 +244,17 @@ cache_source = read_cache_source()
assert not (root / "src/cache.rs").exists()
for fragment in ["mod.rs", "model.rs", "lifecycle.rs", "cold.rs", "dashboard.rs", "tickets.rs", "lookup.rs", "policy.rs", "fill.rs", "collapse.rs", "range.rs", "invalidation.rs", "tests.rs"]:
assert (root / "src/cache" / fragment).is_file(), fragment
cache_mod = (root / "src/cache/mod.rs").read_text()
cache_mod = rust_source(root, "src/cache/mod.rs")
assert 'impl Cache {\n include!(' not in cache_mod, "include! cannot be used directly as Cache impl items"
for fragment in ["lifecycle.rs", "cold.rs", "dashboard.rs", "tickets.rs", "lookup.rs"]:
assert (root / "src/cache" / fragment).read_text().lstrip().startswith("impl Cache {"), fragment
assert rust_source(root, f"src/cache/{fragment}").lstrip().startswith("impl Cache {"), fragment
assert 'disabled_cache_strips_diagnostics_without_exposing_bypass_headers' in cache_source
for marker in ['pub enum MemoryPreset', 'pub enum ColdPreset', 'BACKGROUND_REVALIDATION_LIMIT', 'cleanup_slots']:
assert marker in cache_source, marker
for marker in ['selectedCacheMemoryPreset', 'selectedCacheColdPreset', 'applyRecommendedColdCachePreset', 'data-cache-cold-preset="recommended"']:
assert marker in js or marker in html, marker
assert 'if !self.enabled' in cache_source
proxy_source = (root / "src/proxy/mod.rs").read_text()
proxy_source = rust_source(root, "src/proxy/mod.rs")
assert 'response.extensions().get::<LocalHostResponse>().is_none()' in proxy_source
assert '"cdn-cache-control"' in proxy_source and '"x-cache-resident-age"' in proxy_source
for marker in [
@@ -290,7 +301,7 @@ for marker in [
'selective_purge_removes_matching_cold_object',
]:
assert marker in cache_source, marker
transform_source = (root / "src/transform/mod.rs").read_text()
transform_source = rust_source(root, "src/transform/mod.rs")
for marker in [
'pub struct Settings',
'pub struct Overrides',
@@ -312,9 +323,9 @@ for marker in [
assert marker in transform_source, marker
assert 'collect bounded static response for transformation: {error}' in transform_source
assert '.context("collect bounded static response for transformation")' not in transform_source
lookup_source = (root / 'src/cache/lookup.rs').read_text()
model_source = (root / 'src/cache/model.rs').read_text()
css_minifier_source = (root / 'src/transform/css.rs').read_text()
lookup_source = rust_source(root, 'src/cache/lookup.rs')
model_source = rust_source(root, 'src/cache/model.rs')
css_minifier_source = rust_source(root, 'src/transform/css.rs')
assert 'let Some(_read_lease) = self.try_reserve_transient' in lookup_source
assert 'struct TransientLease {\n _inner: Arc<TransientLeaseInner>,' in model_source
assert 'struct TransientLease(Arc<TransientLeaseInner>);' not in model_source
@@ -326,7 +337,7 @@ for name in ['js.rs', 'css.rs']:
minifier_source = (root / 'src/transform' / name).read_text()
assert 'Vec<char>' not in minifier_source and '.chars().collect' not in minifier_source, name
assert 'into_bytes()' in minifier_source, name
assert 'pub mod transform;' in (root / 'src/lib.rs').read_text()
assert 'pub mod transform;' in rust_source(root, 'src/lib.rs')
for marker in ['cache-cold-gc-interval', 'cache-cold-gc-max-delete', 'settings-tab-transform', 'transform-form', 'transform-memory-budget', 'transform-max-inflight', 'data-transform-preset="uber"', 'cache-cleanup-dialog']:
assert marker in html, marker
for marker in ['cache-transient-memory', 'cache-cold-queue-bytes', 'cache-eviction-limit', 'data-cache-memory-preset="recommended"', 'cache-memory-warning']:
@@ -355,7 +366,7 @@ for marker in ['liveChartSamples = { hits: [], misses: [], bypasses: [] }', 'LIV
assert marker in cache_panel_js, marker
for marker in ['liveChartSamples = { applied: [], cache_hits: [], skipped: [], errors: [] }', 'LIVE_CHART_LIMITS = new Set([60, 120, 300, 600])', 'rustproxy.transform.liveChartSamples', 'performance.now()', 'sparklinePoints(liveChartSamples.applied, 900, 180, 10, peak)', 'slice(-liveChartLimit)']:
assert marker in transform_panel_js, marker
admin_cache_source = (root / 'src/admin/mod.rs').read_text()
admin_cache_source = rust_source(root, 'src/admin/mod.rs')
for marker in ['"transform" => {', 'transform_status', 'cache_cold_cleanup', 'cache_cold_cleanup_job', 'cache_invalidate', 'cache_bans', 'cache_ban_delete', 'selective_cache_invalidation_api_manages_bans_and_rejects_wide_rules_without_confirmation']:
assert marker in admin_cache_source, marker
for marker in [
@@ -378,10 +389,10 @@ for marker in [
]:
assert marker in cache_source, marker
assert 'impl Drop for Candidate' not in cache_source, 'fill accounting must not block moving Candidate fields during finish'
redirect_source = (root / "src/redirect.rs").read_text()
redirect_source = rust_source(root, "src/redirect.rs")
for marker in ["pub struct Host", "pub struct Rule", "strip_prefix", "cache_seconds", "unconditional self-redirect"]:
assert marker in redirect_source, marker
proxy_source = (root / "src/proxy/mod.rs").read_text()
proxy_source = rust_source(root, "src/proxy/mod.rs")
assert 'state.cache.purge(None)' not in proxy_source, 'proxy requests must not globally purge cache'
assert 'request.method() == Method::HEAD && cache_ticket.is_some()' in proxy_source
assert 'RangeSelection::Single' in proxy_source and 'request_range(request.method(), request.headers())' in proxy_source
@@ -389,7 +400,7 @@ assert 'claim_fill(ticket, cache_settings)' in proxy_source and 'cache_collapse_
assert 'schedule_proactive_refresh' in proxy_source and 'cache_proactive_refreshed' in proxy_source
assert 'classify_stale_error' in proxy_source and 'allows_stale_error_status' in proxy_source
assert 'Varnish built-in behavior treats non-GET/HEAD methods as pass' in proxy_source
config_source = (root / "src/config.rs").read_text()
config_source = rust_source(root, "src/config.rs")
assert 'plain HTTP listener' in config_source and 'tls_ports.contains(&443)' in config_source
assert '#[serde(default)]\n pub tls_verify: bool' in config_source
assert 'backend_tls_verification_defaults_off_and_can_be_enabled_explicitly' in config_source
@@ -407,7 +418,7 @@ for marker in [
'backend_timing_header: host.backend_timing_header',
]:
assert marker in config_source, marker
vhost_source = (root / "src/vhost.rs").read_text()
vhost_source = rust_source(root, "src/vhost.rs")
assert 'is_legacy_main_fallback' in vhost_source
assert 'values.length ? values : [{ id: "root"' not in vhosts_js
for marker in [
@@ -423,29 +434,29 @@ for marker in [
'websocket_phase("tunnel_ready")',
]:
assert marker in proxy_source, marker
generic_headers_source = (root / "src/headers.rs").read_text()
generic_headers_source = rust_source(root, "src/headers.rs")
assert '"x-rust-proxy-backend"' in generic_headers_source and '"x-rustproxy-backend-time"' in generic_headers_source
headers_source = (root / "src/proxy/headers.rs").read_text()
headers_source = rust_source(root, "src/proxy/headers.rs")
for marker in ['pub fn restore_admin_cookie', 'admin_cookie_can_be_restored_only_from_captured_fragment']:
assert marker in headers_source, marker
settings_source = (root / "src/settings.rs").read_text()
settings_source = rust_source(root, "src/settings.rs")
for marker in ['pub session_days: u16', 'session_days: 30', '(7..=30).contains(&self.session_days)', 'administration_session_lifetime_is_7_to_30_days_and_hot_apply_only']:
assert marker in settings_source, marker
auth_source = (root / "src/auth/mod.rs").read_text()
auth_store = (root / "src/auth/store.rs").read_text()
auth_source = rust_source(root, "src/auth/mod.rs")
auth_store = rust_source(root, "src/auth/store.rs")
for marker in ['30 * 24 * 60 * 60', 'session_cookie(secret: &str, secure: bool, max_age_seconds: i64)', 'browser_session_lifetime_is_configurable_without_sliding_expiry', 'session_cookie_uses_configured_remaining_lifetime']:
assert marker in auth_source, marker
for marker in ['create_browser_session', 'session_at_with_browser_lifetime', 'browser session lifetime must be 7..30 days', "created_at + ?"]:
assert marker in auth_store, marker
upstream_source = (root / "src/upstream.rs").read_text()
upstream_source = rust_source(root, "src/upstream.rs")
for marker in ['pub accept_local_listener_risk: bool', '!self_target || self.accept_local_listener_risk', 'explicit_risk_acceptance_allows_local_listener_but_not_private_policy_bypass']:
assert marker in upstream_source, marker
transport_tests = (root / "tests/transport_config.rs").read_text()
assert 'local_listener_backend_requires_explicit_risk_acceptance' in transport_tests and '127.0.0.1:9090' in transport_tests
runtime_source = (root / "src/runtime.rs").read_text()
runtime_source = rust_source(root, "src/runtime.rs")
for marker in ['fn cache_revision', 'CacheInvalidation::None', 'operational_saves_keep_cache_identity_but_cache_affecting_saves_rotate_it']:
assert marker in runtime_source, marker
admin = (root / "src/admin/mod.rs").read_text()
admin = rust_source(root, "src/admin/mod.rs")
for marker in [
"fn admin_request_authority",
"Version::HTTP_2 | Version::HTTP_3",
@@ -458,7 +469,7 @@ for marker in ['"/api/config/{section}"', 'async fn update_section', 'section_up
assert marker in admin, marker
for route in ['/overview', '/vhosts', '/redirects', '/404-hosts', '/streams', '/acl-profiles', '/configuration', '/tls', '/cache', '/transform', '/logging', '/settings']:
assert f'.route("{route}", get(public::index))' in admin, route
app_js = (root / "src/admin/web/app.js").read_text()
app_js = read_app_js(root)
for marker in ['const PANEL_PATHS', 'history.pushState', 'window.addEventListener("popstate"', 'async function saveSection', 'async function revalidateSession', 'Object.values(PANEL_PATHS), "/configuration"', 'certificateCovers', 'covered_hosts', 'refreshCertificateInventory', 'certificateDetails', 'certificate-domain-pills', 'certificateIssuerName', 'certificateDaysRemaining', 'certificateRenewalStatus']:
assert marker in app_js, marker
for marker in ['.certificate-details', '.certificate-domain-pills', '.certificate-card .pill', '.certificate-operation-card', '.renewal-meta', '#panel-tls .certificate-tabs']:
@@ -495,13 +506,13 @@ for marker in ['function setOptionalMetric', 'setOptionalMetric("process-rss-ano
assert marker in app_js, marker
for marker in ['/api/certificate-api', 'certificate-api-form', 'certificate-api-revoke-all', 'certificate-api-credentials', 'data-cache-settings-tab']:
assert marker in settings_js or marker in html, marker
db_source = (root / "src/db.rs").read_text()
acme_source = (root / "src/acme.rs").read_text()
main_source = (root / "src/main.rs").read_text()
logging_source = (root / "src/logging.rs").read_text()
secret_store_source = (root / "src/secret_store.rs").read_text()
backup_source = (root / "src/backup.rs").read_text()
config_source = (root / "src/config.rs").read_text()
db_source = rust_source(root, "src/db.rs")
acme_source = rust_source(root, "src/acme.rs")
main_source = rust_source(root, "src/main.rs")
logging_source = rust_source(root, "src/logging.rs")
secret_store_source = rust_source(root, "src/secret_store.rs")
backup_source = rust_source(root, "src/backup.rs")
config_source = rust_source(root, "src/config.rs")
acme_worker_source = (root / "scripts/acme_provider.py").read_text()
for feature_marker in [
"AES_256_GCM", "master.key", "O_NOFOLLOW", "migrate_acme_credentials",
@@ -545,7 +556,7 @@ for marker in [
'LocalAdminCertificateVerifier', 'detect_local_admin_scheme',
'local_admin_scheme_from_probe', 'admin.uri("/api/live-logs")',
]:
assert marker in main_source or marker in (root / 'src/auth/store.rs').read_text(), marker
assert marker in main_source or marker in rust_source(root, 'src/auth/store.rs'), marker
assert '.uri(format!("http://{addr}/api/live-logs"))' not in main_source
assert 'http://{addr}/healthz' in main_source and 'StatusCode::PERMANENT_REDIRECT' in main_source
assert 'Ok(line) if command_tx.send(line).is_ok()' not in main_source, 'do not move String from a match guard in --livelogs stdin handling'
@@ -567,29 +578,29 @@ for marker in [
'state.start_update_check(update_check);',
]:
assert marker in main_source, marker
runtime_source = (root / "src/runtime.rs").read_text()
runtime_source = rust_source(root, "src/runtime.rs")
assert 'pub software_update: Arc<crate::update_check::SharedStatus>' in runtime_source
assert 'pub fn start_update_check(self: &Arc<Self>, config: crate::update_check::Config)' in runtime_source
assert 'payload["software_update"] = json!(state.software_update.snapshot());' in admin
settings_rust = (root / 'src/settings.rs').read_text()
settings_rust = rust_source(root, 'src/settings.rs')
assert 'pub struct StartupLocks' in settings_rust and 'fixed by systemd/startup' in settings_rust
logging_rust = (root / 'src/logging.rs').read_text()
logging_rust = rust_source(root, 'src/logging.rs')
assert 'pub per_vhost: bool' in logging_rust and 'default_vhost_log_directory' in logging_rust and '_unmatched' in logging_rust
pages_rust = (root / 'src/pages.rs').read_text()
pages_rust = rust_source(root, 'src/pages.rs')
assert 'validate_local_response' in pages_rust and '(200..=599).contains(&status)' in pages_rust and '204 | 205 | 304' in pages_rust
assert 'store.load_certificate_renewals().await?' in main_source and 'state.acme.restore_renewals(renewal_observations)' in main_source
assert 'renewals.json' not in main_source
upgrade_source = (root / 'scripts/upgrade.py').read_text()
assert 'legacy = certs_dir / "renewals.json"' in upgrade_source and 'removed_obsolete_runtime_state' in upgrade_source and 'legacy-data' not in upgrade_source and 'certs_dir.is_symlink()' in upgrade_source
assert '.managed-update' in main_source and 'flush_hot_to_cold_for_update' in main_source
tls_source = (root / "src/tls.rs").read_text()
tls_source = rust_source(root, "src/tls.rs")
assert 'pub fn validate_certificate_removals' in tls_source and 'administration panel' in tls_source
assert 'pub fn effective_cipher_suites' in tls_source
vhost_source = (root / 'src/vhost.rs').read_text()
vhost_source = rust_source(root, 'src/vhost.rs')
assert 'pub websocket_rfc9220: bool' in vhost_source and 'RFC 9220 requires WebSocket support to be enabled' in vhost_source
for marker in ['pub struct ProxyTimeouts', 'connect_timeout_seconds', 'response_header_timeout_seconds', 'read_timeout_seconds', 'send_timeout_seconds']:
assert marker in vhost_source, marker
docker_source = (root / 'src/docker.rs').read_text()
docker_source = rust_source(root, 'src/docker.rs')
for marker in ['pub poll_interval_seconds: u64', 'pub acl_profile_id: Option<String>', 'pub proxy_timeouts: crate::vhost::ProxyTimeouts', 'refresh(&self, settings: &Settings, force: bool)', 'poll_interval_seconds.saturating_mul(1000)']:
assert marker in docker_source, marker
docker_js = (root / 'src/admin/web/docker.js').read_text()
@@ -599,33 +610,33 @@ agent_installer = (root / 'docker-agent/install.sh').read_text()
assert 'Bearer token:' in agent_installer and 'RUSTPROXY_DOCKER_AGENT_TOKEN=' in agent_installer
assert 'Kind::Builtin' in pages_rust and 'builtin_application_page' in pages_rust
assert 'pub covered_hosts: Vec<String>' in tls_source and 'fn certificate_dns_names' in tls_source and 'pub fn certificate_covered_hosts' in tls_source and 'legacy_certificate_coverage_can_be_read_from_existing_pem' in tls_source and 'assert_eq!(a.covered_hosts' in tls_source
acl_source = (root / 'src/acl.rs').read_text()
acl_source = rust_source(root, 'src/acl.rs')
assert '/Ubuntu%2014.04%20LTS/' in acl_source and 'repeated_slashes_are_normalized_for_routing' in acl_source and 'merge_slashes' in acl_source
policies_source = (root / 'tests/policies.rs').read_text()
assert 'percent_encoded_spaces_are_valid_request_paths' in policies_source and 'repeated_slashes_route_normally_but_reach_upstream_unchanged' in policies_source and 'local_location_response_uses_response_rules_without_opening_backend' in policies_source and 'local_location_response_still_respects_route_acl' in policies_source
http3_source = (root / "src/http3.rs").read_text()
http3_source = rust_source(root, "src/http3.rs")
drop_impl = http3_source.split('impl Drop for ReceiveBody', 1)[1].split('#[cfg(test)]', 1)[0]
assert 'self.stream.stop_sending(' not in drop_impl
for marker in ['h3::quinn::RecvStream', 'websocket_rfc9220_on(local)', 'run_h3', 'H3_REQUEST_CANCELLED']:
assert marker in http3_source or marker in (root / 'src/proxy/websocket.rs').read_text(), marker
assert marker in http3_source or marker in rust_source(root, 'src/proxy/websocket.rs'), marker
assert 'h3_quinn' not in http3_source and 'h3_quinn' not in (root / 'tests/http3.rs').read_text()
h3_test = (root / 'tests/http3.rs').read_text()
assert 'RFC 9220: Extended CONNECT negotiates WebSocket on the same H3 stream.' in h3_test and '"websocket_rfc9220":true' in h3_test
assert 'Method::CONNECT' in h3_test and 'h3::ext::Protocol' in h3_test and '.send_data(' in h3_test
admin_source = (root / 'src/admin/mod.rs').read_text()
admin_source = rust_source(root, 'src/admin/mod.rs')
for marker in ['external_admin_authority', 'external_admin_scheme', 'trusted_admin_forwarded_proto', 'reverse_proxy_dns_allowlist_uses_external_port_and_keeps_direct_port_available', 'trusted_https_reverse_proxy_accepts_external_origin_and_refreshes_secure_cookie']:
assert marker in admin_source, marker
ws_source = (root / 'src/proxy/websocket.rs').read_text()
ws_source = rust_source(root, 'src/proxy/websocket.rs')
assert 'upstream: Upgraded' in ws_source
assert 'timeout(Duration::from_secs(10), upstream)' not in ws_source
for marker in ['websocket_phase("tunnel_started")', 'websocket_phase("tunnel_closed")', 'h3_reset("H3_REQUEST_CANCELLED")']:
assert marker in ws_source, marker
for marker in ['http_version', 'transport', 'websocket_bootstrap', 'websocket_phase', 'websocket_error', 'h3_reset_code', 'upstream_status']:
assert marker in (root / 'src/logging.rs').read_text(), marker
diagnostics_source = (root / 'src/diagnostics.rs').read_text() + (root / 'src/system_stats/mod.rs').read_text() + (root / 'src/system_stats/linux.rs').read_text()
assert marker in rust_source(root, 'src/logging.rs'), marker
diagnostics_source = rust_source(root, 'src/diagnostics.rs') + rust_source(root, 'src/system_stats/mod.rs') + rust_source(root, 'src/system_stats/linux.rs')
for marker in ['process_rss_anon_bytes', 'process_rss_file_bytes', 'process_rss_shmem_bytes', 'process_data_bytes', 'process_swap_bytes', 'RssAnon', 'RssFile', 'RssShmem', 'VmData', 'VmSwap']:
assert marker in diagnostics_source, marker
prometheus_source = (root / 'src/prometheus.rs').read_text()
prometheus_source = rust_source(root, 'src/prometheus.rs')
for marker in ['allow_trusted_network_without_token', 'include_docker_vhosts', 'include_streams', 'include_logging', 'rust_proxy_docker_vhost_{name}', 'rust_proxy_docker_backend_{name}', 'rust_proxy_geoip_loaded', 'not_after_timestamp_seconds', 'ewma_latency_seconds', 'passive_failures', 'active_health_failures_total', 'passive_health_failures_total', 'passive_http_5xx_total', 'passive_timeouts_total', 'passive_connect_errors_total', 'passive_io_errors_total', 'passive_slow_total', 'http_5xx_total', 'timeouts_total', 'connect_errors_total', 'io_errors_total', 'slow_responses_total', 'rust_proxy_log_sink_queue_dropped_total', 'rust_proxy_not_found_hosts_configured']:
assert marker in prometheus_source, marker
assert 'if docker_targets.contains_key(&pool.id)' in prometheus_source
@@ -638,7 +649,7 @@ for marker in ['cache-memory-breakdown', 'cache-transient-breakdown', 'cache-col
for marker in ['validate_h3', 'H3Tunnel', 'h3_client_to_backend', 'backend_to_h3', 'rfc9220_bootstrap_uses_extended_connect_without_h1_proof_headers']:
assert marker in ws_source, marker
for marker in ['PrefixPriority', 'RegexInsensitive', 'LocationResponse', 'pub rewrite: PathRewrite']:
assert marker in (root / 'src/vhost.rs').read_text(), marker
assert marker in rust_source(root, 'src/vhost.rs'), marker
for marker in ['rewritten_path', 'nginx_style_location_precedence_exact_priority_regex_prefix', 'location_rewrites_are_normalized_and_regex_captures_expand', 'custom_location_response_is_validated']:
assert marker in config_source, marker
for marker in ['local_location_response', 'route.rewritten_path(&path)', 'encoded_origin_path', 'client_ip.to_string()']:
@@ -650,11 +661,11 @@ for marker in ['locationMatchRegex', 'headersVisualBuilder', 'headersAdvancedJso
assert marker in vhosts_js, marker
for marker in ['lastApiLatencyMs', 'cacheMemorySamples', 'cacheTransientSamples', 'cacheColdStorageSamples', 'cacheHitSamples', 'processCpuSamples', 'processRssSamples', 'networkRxSamples', 'responseLatencySamples', 'client_ip']:
assert marker in app_js, marker
logging_source = (root / 'src/logging.rs').read_text()
logging_source = rust_source(root, 'src/logging.rs')
assert 'pub client_ip: Option<String>' in logging_source and '"client_ip" => entry.client_ip' in logging_source
for marker in ['check_rustproxy_api', 'response time', 'backend']:
assert marker in (root / 'nagios/README.md').read_text(), marker
stream_source = (root / "src/stream.rs").read_text()
stream_source = rust_source(root, "src/stream.rs")
for marker in ["pub struct Metrics", "pub struct MetricsView", "struct ActiveSession", "sessions_total", "sessions_completed", "packets_in", "packets_out", "metrics_view_reports_l4_counters"]:
assert marker in stream_source, marker
transport_doc = (root / "docs/TRANSPORT.md").read_text()
@@ -663,10 +674,10 @@ api_access_doc = (root / "docs/API_ACCESS.md").read_text()
assert 'accept_local_listener_risk: true' in transport_doc and '127.0.0.1:9090' in transport_doc
assert 'accept_local_listener_risk=true' in security_doc and 'including port 9090' in security_doc
assert '7–30' in api_access_doc and 'default 30' in api_access_doc
not_found_source = (root / 'src/not_found.rs').read_text()
not_found_source = rust_source(root, 'src/not_found.rs')
for marker in ['pub struct Host', 'pub struct CompiledHost', 'default_status', 'crate::pages::Page']:
assert marker in not_found_source, marker
pages_source = (root / 'src/pages.rs').read_text()
pages_source = rust_source(root, 'src/pages.rs')
assert 'pub struct MinimalWelcome' in pages_source and 'HeaderValue::from_static("no-store")' in pages_source
assert 'builtin_welcome_is_minimal_and_never_cacheable' in pages_source
assert 'minimal_welcome' in proxy_source and 'cache-control' in proxy_source
@@ -694,15 +705,15 @@ expressions = '\n'.join(target.get('expr','') for panel in grafana['panels'] for
for marker in ['rust_proxy_process_rss_bytes', 'rust_proxy_cache_transient_bytes', 'rust_proxy_backend_latency_seconds', 'rust_proxy_stream_active', 'rust_proxy_log_sink_queue_dropped_total']:
assert marker in expressions, marker
# 0.19.0 compression/protocol/dashboard UX regressions.
compression_source = (root / "src/compression.rs").read_text()
metrics_source = (root / "src/metrics.rs").read_text()
admin_source = (root / "src/admin/mod.rs").read_text()
compression_source = rust_source(root, "src/compression.rs")
metrics_source = rust_source(root, "src/metrics.rs")
admin_source = rust_source(root, "src/admin/mod.rs")
style_source = (root / "src/admin/web/style.css").read_text()
docker_ui = (root / "src/admin/web/docker.js").read_text()
for marker in ["pub enum AppliedEncoding", "AppliedEncoding::Gzip", "AppliedEncoding::Brotli", "AppliedEncoding::Zstd", "AppliedEncoding::Deflate"]:
assert marker in compression_source, marker
assert "quality_weights_can_select_each_enabled_codec" in compression_source
diagnostics_source = (root / "src/diagnostics.rs").read_text() + (root / "src/system_stats/mod.rs").read_text() + (root / "src/system_stats/linux.rs").read_text()
diagnostics_source = rust_source(root, "src/diagnostics.rs") + rust_source(root, "src/system_stats/mod.rs") + rust_source(root, "src/system_stats/linux.rs")
for marker in ["pub struct NetworkInterfaceView", "pub network_interfaces: Vec<NetworkInterfaceView>", "sysinfo::Networks::new_with_refreshed_list", "system.network_stats", "collect_network_systemstat", "normalize_network_interfaces", "merge_network_interfaces"]:
assert marker in diagnostics_source, marker
assert "interfaces.truncate(64)" not in diagnostics_source, "network inventory must not silently truncate interfaces"
@@ -717,7 +728,7 @@ assert 'id="network-interface-charts"' in html
assert 'compressionCountersHelp' not in html
assert "dockerOpenApp" in docker_ui and "proxiedUrl(agent, hostname)" in docker_ui
# 0.19.0 Docker-vhost controls: chip aliases, default agent ACL, redirect/WebSockets/cache.
docker_source = (root / "src/docker.rs").read_text()
docker_source = rust_source(root, "src/docker.rs")
management_ui = (root / "src/admin/web/management.js").read_text()
for marker in ["function aliasEditor(", "host-chip-editor docker-alias-editor", ".docker-force-ssl", ".docker-websockets", ".docker-cache-enabled", ".docker-agent-acl-profile"]:
assert marker in docker_ui, marker
@@ -727,7 +738,7 @@ assert "agent.acl_profile_id === profile.id" in management_ui
assert 'payload["backend_pool_domains"]' in admin_source and "status.backend_pool_domains" in vhosts_js
assert 'body[data-density="compact"]' in style_source and '--ui-control: 22px' in style_source
assert 'rust_proxy_http1_requests_total' in expressions
vhost_source = (root / "src/vhost.rs").read_text()
vhost_source = rust_source(root, "src/vhost.rs")
for marker in ["DEFAULT_PROXY_CONNECT_TIMEOUT_SECONDS: u64 = 10", "DEFAULT_PROXY_RESPONSE_HEADER_TIMEOUT_SECONDS: u64 = 120", "DEFAULT_PROXY_READ_TIMEOUT_SECONDS: u64 = 60", "DEFAULT_PROXY_SEND_TIMEOUT_SECONDS: u64 = 60", "proxy_timeouts_have_explicit_safe_defaults_but_keep_null_compatibility"]:
assert marker in vhost_source, marker
assert 'defaultProxyTimeouts = () => ({ connect_timeout_seconds: 10, response_header_timeout_seconds: 120, read_timeout_seconds: 60, send_timeout_seconds: 60 })' in vhosts_js
@@ -764,7 +775,7 @@ assert 'pub transformed: bool' in cache_source and 'annotate_transformed' in cac
assert 'x-cache-status' in cache_source and 'Cache-Status (RFC 9211)' in html
assert 'generated_vhost_inherits_global_server_header_policy' in docker_source and 'effective.vhosts[0].server_header.is_none()' in docker_source
assert '.insert("x-rustproxy-backend-time", value)' in proxy_source and '.insert("x-rust-proxy-backend-time", value)' not in proxy_source
assert 'x-rustproxy-backend-time' in (root / "src/headers.rs").read_text()
assert 'x-rustproxy-backend-time' in rust_source(root, "src/headers.rs")
# Expanded upstream connection diagnostics must retain nested Hyper/rustls/io causes.
for marker in [
"fn format_error_chain(",
@@ -802,7 +813,7 @@ assert '#[serde(default = "default_admin_theme")]' in admin_source and 'matches!
assert 'bindSettingsForm("pages-form", next => { next.pages = global.read(); }, "pages")' in management_ui
assert '"pages" => {' in admin_source and 'config.pages =' in admin_source
assert 'default_pages_section_accepts_the_standard_value_payload' in admin_source
logging_source = (root / "src/logging.rs").read_text()
logging_source = rust_source(root, "src/logging.rs")
assert 'pub const LIVE_WINDOW: usize = 256;' in logging_source
assert 'pub const HISTORY_CAPACITY: usize = 4096;' in logging_source
assert 'retained_history_is_larger_than_the_live_snapshot_but_still_bounded' in logging_source
@@ -819,18 +830,18 @@ traffic_panel_js = (root / "src/admin/web/traffic-panel.js").read_text()
assert 'id="panel-traffic"' in html and 'data-panel="traffic"' in html
for marker in ['/api/traffic', 'trafficTopCountries', 'trafficTopUserAgents', 'trafficTopClientIps', 'traffic-donut', 'rustProxyTrafficPanel']:
assert marker in traffic_panel_js or marker in html, marker
traffic_source = (root / "src/traffic.rs").read_text()
traffic_source = rust_source(root, "src/traffic.rs")
for marker in ['QUEUE_CAPACITY: usize = 2048', 'TOP_CAPACITY: usize = 32', 'MAX_VHOSTS: usize = 64', 'self.tx.try_send(sample)', 'client_ips: TopTable']:
assert marker in traffic_source, marker
assert 'if (envelope) render();' in (root / "src/admin/web/web-server.js").read_text()
assert 'pub capture_user_agent: bool' in logging_source and 'pub capture_country: bool' in logging_source
assert 'spawn_blocking(crate::diagnostics::trim_allocator)' in (root / 'src/runtime.rs').read_text()
assert 'spawn_blocking(crate::diagnostics::trim_allocator)' in rust_source(root, 'src/runtime.rs')
assert 'fn trim_hot_idle(&self)' in cache_source and 'hot_auto_trim_target_percent' in cache_source
assert 'id="cache-domain-filter"' in html and 'cacheDomainFilterEnabled' in html and 'cacheDomainFilterDisabled' in html
assert 'const visibleDomains = (data, groups) =>' in cache_panel_js and 'scoped?.settings?.enabled ?? data.settings?.enabled ?? false' in cache_panel_js
assert 'groups = d.domains || [], shownGroups = visibleDomains(data, groups)' in cache_panel_js
assert 'replaceChildren(...shownGroups.map(row =>' in cache_panel_js
balance_source = (root / 'src/balance.rs').read_text()
balance_source = rust_source(root, 'src/balance.rs')
assert 'traffic_rate_drops_to_zero_after_an_idle_sample_window' in balance_source and 'if delta == 0 {' in balance_source and 'sample.rate = 0.0;' in balance_source
all_admin_js = "\n".join(path.read_text() for path in (root / "src/admin/web").glob("*.js"))
assert not re.search(r'(?<![A-Za-z])(?:window\.)?(?:alert|confirm)\s*\(', all_admin_js), "native browser alert/confirm returned"
@@ -854,7 +865,7 @@ assert 'form.reset(); window.rustProxyCertificates?.close();' in integrations_ui
assert '$("cert-import-pem").value = ""' not in integrations_ui_0194 and '$("cert-import-key").value = ""' not in integrations_ui_0194
assert 'throw fieldError(row.querySelector(".docker-agent-listener-choices")' in docker_ui_0194
assert '#docker-agents-form>.form-actions {' in style_source and 'justify-content: flex-start' in style_source
deploy_source = (root / "scripts/deploy.py").read_text()
deploy_source = read_deploy_source()
assert "SHELL_PATH_PROFILE = Path('/etc/profile.d/rustproxy-path.sh')" in deploy_source
assert 'install_shell_path(prefix)' in deploy_source and 'check_shell_path(prefix)' in deploy_source and "'shell_path_action':'install' if args.mode == 'install' else 'check-only'" in deploy_source
assert 'grid-template-columns: minmax(0, 1fr)' in style_source and '.log-column-option:hover' in style_source
@@ -874,7 +885,7 @@ assert '<span class="version">' not in html, "duplicate top-right version label
assert '<div class="edition">INDEPENDENT BY DESIGN <span>' not in html, "release version returned beside the dashboard brand"
assert '<div class="edition">INDEPENDENT BY DESIGN</div>' in html
# tls_verify=false must not feed legacy appliance certificates back through webpki.
upstream_source = (root / "src/upstream.rs").read_text(encoding="utf-8")
upstream_source = rust_source(root, "src/upstream.rs")
assert "BackendCertificateVerificationDisabled { supported_schemes }" in upstream_source
disabled_verifier = upstream_source.split("impl ServerCertVerifier for BackendCertificateVerificationDisabled", 1)[1].split("pub fn client(", 1)[0]
assert disabled_verifier.count("Ok(HandshakeSignatureValid::assertion())") == 2
@@ -882,9 +893,9 @@ assert "WebPkiServerVerifier" not in disabled_verifier
assert '.docker-route-grid {' in style_source and 'align-items: start' in style_source and '.docker-acl-grid {' in style_source
# 0.22.3 cache-modal, RFC8441/h2c and active-tunnel contracts.
server_source = (root / "src/server.rs").read_text()
websocket_source = (root / "src/proxy/websocket.rs").read_text()
vhost_source = (root / "src/vhost.rs").read_text()
server_source = rust_source(root, "src/server.rs")
websocket_source = rust_source(root, "src/proxy/websocket.rs")
vhost_source = rust_source(root, "src/vhost.rs")
integrations_0221 = (root / "src/admin/web/integrations.js").read_text()
http2_test = (root / "tests/http2.rs").read_text()
transport_test = (root / "tests/transport_config.rs").read_text()
@@ -940,7 +951,7 @@ for memory_marker_0230 in [
'http2_active_connections',
]:
assert memory_marker_0230 in server_source or memory_marker_0230 in metrics_source, memory_marker_0230
cache_fill_0230 = (root / 'src/cache/fill.rs').read_text()
cache_fill_0230 = rust_source(root, 'src/cache/fill.rs')
assert 'let body_allocation = self.data.capacity().max(self.data.len());' in cache_fill_0230
assert 'let cost = hot_entry_cost(' in cache_fill_0230
assert 'fn hot_entry_cost(' in cache_source
@@ -1008,7 +1019,7 @@ assert 'prior knowledge' in transport_doc and 'Upgrade: h2c' in transport_doc an
assert (root / "docs/V0.24.1_AUDIT.md").is_file() and (root / "docs/V0.24.0_AUDIT.md").is_file() and (root / "docs/V0.23.2_AUDIT.md").is_file() and (root / "docs/V0.23.1_AUDIT.md").is_file() and (root / "docs/V0.23.0_AUDIT.md").is_file() and (root / "docs/V0.22.3_AUDIT.md").is_file()
# 0.22.3 replay-safe retry and ordinary H2 upstream contracts.
balance_0222 = (root / "src/balance.rs").read_text()
balance_0222 = rust_source(root, "src/balance.rs")
for marker_0222 in [
"pub struct RetryPolicy", "pub max_retries: u8", "pub retry_statuses: Vec<u16>",
"pub fn select_retry", "retry_attempts_total", "retry_successes_total",
@@ -1022,9 +1033,9 @@ for marker_0222 in [
"explicit_http2_backend_uses_http2_request_version",
]:
assert marker_0222 in proxy_source, marker_0222
upstream_0222 = (root / "src/upstream.rs").read_text()
upstream_0222 = rust_source(root, "src/upstream.rs")
assert "explicit_h2c_backend_uses_http2_prior_knowledge" in upstream_0222
vhosts_0222 = (root / "src/admin/web/vhosts.js").read_text()
vhosts_0222 = read_vhosts_js(root)
for marker_0222 in ["retry-max", "retry-connect", "retry-timeouts", "retry-statuses"]:
assert marker_0222 in vhosts_0222, marker_0222
for marker_0222 in [
@@ -1042,7 +1053,7 @@ assert 'json!({"id":m.definition.id, "url":m.definition.url' not in balance_0222
for marker_0222 in ["member-max-concurrent", "member-queue-timeout", "vhLastFailure", "vhLastRecovery"]:
assert marker_0222 in vhosts_0222 or marker_0222 in html, marker_0222
for marker_0222 in ["CertificateMetadata", "certificate_public_metadata", "x509_time_parser_handles_utc_and_generalized_time_with_offsets"]:
assert marker_0222 in (root / "src/tls.rs").read_text(), marker_0222
assert marker_0222 in rust_source(root, "src/tls.rs"), marker_0222
for marker_0222 in [
'"max_concurrent_requests"', '"queue_timeout_ms"', '"certificate_issuer"',
'"days_remaining"', '"expiry_status"', '"last_renewal_error"'
@@ -1072,13 +1083,13 @@ for marker_0223 in [
'"operation": "unchanged"', 'config.tls.certificates.push(crate::tls::Certificate',
]:
assert marker_0223 in admin, marker_0223
runtime_0223 = (root / 'src/runtime.rs').read_text()
runtime_0223 = rust_source(root, 'src/runtime.rs')
for marker_0223 in ['pub async fn reload_certificates', 'configured certificates reloaded from disk']:
assert marker_0223 in runtime_0223, marker_0223
main_0223 = (root / 'src/main.rs').read_text()
main_0223 = rust_source(root, 'src/main.rs')
for marker_0223 in ['TlsCommand::Deploy', '/api/certificates/deploy', '/api/certificates/reload', 'read_external_pem']:
assert marker_0223 in main_0223, marker_0223
tls_0223 = (root / 'src/tls.rs').read_text()
tls_0223 = rust_source(root, 'src/tls.rs')
for marker_0223 in ['pub fn stage_external_pair', 'pub fn reconcile_external_pair', 'ExternalPairDeployment::Unchanged', 'external-', 'remove_external_pair']:
assert marker_0223 in tls_0223, marker_0223
for marker_0223 in ['"/api/certificates/reload"', '"CertificateReloadResult"', '"/api/certificates/deploy"', '"CertificateDeploy"', '"CertificateDeployResult"']:
@@ -1087,9 +1098,9 @@ assert 'api("/api/certificates/reload"' in app_js
assert 'certificateAdminRestartRequired' in app_js
# 0.24.0 H2 lifecycle contracts retained by 0.24.1.
server_0240 = (root / "src/server.rs").read_text()
settings_0240 = (root / "src/settings.rs").read_text()
config_0240 = (root / "src/config.rs").read_text()
server_0240 = rust_source(root, "src/server.rs")
settings_0240 = rust_source(root, "src/settings.rs")
config_0240 = rust_source(root, "src/config.rs")
for marker_0240 in [
"H2ConnectionState", "H2StreamLease", "H2TrackedBody",
"wait_for_h2_idle", "graceful_shutdown()", "H2ShutdownCause::Lifetime",
@@ -1101,16 +1112,16 @@ for marker_0240 in [
for marker_0240 in ["Http2Connections", "idle_timeout_seconds", "max_connection_lifetime_seconds", "drain_timeout_seconds"]:
assert marker_0240 in settings_0240, marker_0240
assert "pub http2: crate::settings::Http2Connections" in config_0240
assert "pub http2_settings: Option<crate::settings::Http2Connections>" in (root / "src/vhost.rs").read_text()
assert "pub http2_settings: Option<crate::settings::Http2Connections>" in rust_source(root, "src/vhost.rs")
assert "serve_frontend_with_http2" in main_source and "binding.http2_settings.unwrap_or_default()" in main_source
assert 'renderHttp2Settings' in integrations_js and 'collectHttp2Listeners' in integrations_js
assert '"Http2ConnectionSettings"' in openapi and '"max_connection_lifetime_seconds"' in openapi
# 0.24.1 shared statistics/runtime-info/settings-navigation contracts.
system_stats_0241 = (root / "src/system_stats/mod.rs").read_text()
linux_stats_0241 = (root / "src/system_stats/linux.rs").read_text()
main_0241 = (root / "src/main.rs").read_text()
admin_0241 = (root / "src/admin/mod.rs").read_text()
system_stats_0241 = rust_source(root, "src/system_stats/mod.rs")
linux_stats_0241 = rust_source(root, "src/system_stats/linux.rs")
main_0241 = rust_source(root, "src/main.rs")
admin_0241 = rust_source(root, "src/admin/mod.rs")
settings_js_0241 = (root / "src/admin/web/settings.js").read_text()
assert not (root / "src/system_stats/bsd.rs").exists(), "per-BSD parser backend must not return"
assert manifest["target"]['cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly", target_os = "macos", target_os = "windows"))']["dependencies"]["systemstat"] == "=0.2.7"
@@ -1145,14 +1156,14 @@ assert '"error_log" => {' not in admin_0241 and 'request("/api/config/error_log"
assert '"error_log"' in openapi and 'logging, error_log, forwarding' not in openapi
assert 'logging_section_persists_error_log_settings_atomically' in admin_0241 and 'error_log_is_not_a_standalone_configuration_section' in admin_0241
assert 'location.pathname === "/logging"' in settings_js_0241
assert '"RuntimeInformation"' in openapi and '"version": "0.25.0"' in openapi
assert '"RuntimeInformation"' in openapi and '"version": "0.25.1"' in openapi
# 0.24.1 compiler and hostname-cardinality regressions.
tls_0241 = (root / "src/tls.rs").read_text()
vhost_0241 = (root / "src/vhost.rs").read_text()
redirect_0241 = (root / "src/redirect.rs").read_text()
not_found_0241 = (root / "src/not_found.rs").read_text()
docker_0241 = (root / "src/docker.rs").read_text()
tls_0241 = rust_source(root, "src/tls.rs")
vhost_0241 = rust_source(root, "src/vhost.rs")
redirect_0241 = rust_source(root, "src/redirect.rs")
not_found_0241 = rust_source(root, "src/not_found.rs")
docker_0241 = rust_source(root, "src/docker.rs")
integrations_0241 = (root / "src/admin/web/integrations.js").read_text()
docker_js_0241 = (root / "src/admin/web/docker.js").read_text()
assert "future::Future" not in server_0240
@@ -1190,5 +1201,5 @@ for schema_name in ["RedirectHost", "NotFoundHost"]:
node = openapi_0241["components"]["schemas"][schema_name]["properties"]["frontend"]["properties"]["hosts"]
assert "maxItems" not in node, schema_name
print("PASS: 0.25.0 manifest/package, shared system-statistics/runtime metadata, Settings logging, retained H2, Debian/Grafana/Prometheus/404-host/custom-location/path/cache/dashboard/Nagios UI/source contracts, stopped legacy-renewal removal, session/admin/transport contracts, deterministic package source and embedded SQLite schema-v7 migrations.")
print("PASS: 0.25.1 manifest/package, shared system-statistics/runtime metadata, Settings logging, retained H2, Debian/Grafana/Prometheus/404-host/custom-location/path/cache/dashboard/Nagios UI/source contracts, stopped legacy-renewal removal, session/admin/transport contracts, deterministic package source and embedded SQLite schema-v7 migrations.")
print("NOT VERIFIED: Rust parsing, types, compilation, linking or runtime behavior. Run ./dev.sh test.")