v0.32.5
This commit is contained in:
1 parent
8b9ca4db44
commit
00218a72df
35 files changed
+790
-870
No files matched your search
@@ -7,7 +7,7 @@ import tomllib
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
read = lambda path: (root / path).read_text(encoding='utf-8')
|
||||
version = tomllib.loads(read('Cargo.toml'))['package']['version']
|
||||
assert version == '0.32.4', version
|
||||
assert version == '0.32.5', version
|
||||
spec = json.loads(read('src/admin/openapi.json'))
|
||||
assert spec['info']['version'] == version
|
||||
paths = spec['paths']
|
||||
@@ -64,5 +64,5 @@ for language in ('en_US', 'pl_pl'):
|
||||
for key in ('certificateApiView', 'certificateApiEdit', 'certificateApiSave', 'certificateApiRegenerate',
|
||||
'certificateApiRegenerateConfirm', 'certificateApiTokenHidden', 'certificateApiCreatedAt'):
|
||||
assert strings.get(key), (language, key)
|
||||
assert '0.32.4' in read('docs/TEST_REPORT.md')
|
||||
assert '0.32.5' in read('docs/TEST_REPORT.md')
|
||||
print('PASS: 0.31.9 per-credential API routes, separated metadata editing/token regeneration, OpenAPI security, UI and locales (source-only).')
|
||||
@@ -24,7 +24,7 @@ def read_docker_agent_source() -> str:
|
||||
|
||||
preflight(root)
|
||||
manifest = tomllib.loads((root / "Cargo.toml").read_text())
|
||||
assert manifest["package"]["version"] == "0.32.4"
|
||||
assert manifest["package"]["version"] == "0.32.5"
|
||||
assert manifest["dependencies"]["quinn"]["version"] == "0.11.12"
|
||||
h3dep = manifest["dependencies"]["h3"]
|
||||
assert h3dep["package"] == "hpx-h3" and h3dep["version"] == "=2.5.20" and "quinn" in h3dep["features"]
|
||||
@@ -32,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.32.4"' in lock
|
||||
assert 'name = "rust-proxy"\nversion = "0.32.5"' 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.32.4",
|
||||
"CHANGELOG.md": "## 0.32.4",
|
||||
"ROADMAP.md": "## 0.32.4",
|
||||
"AGENTS.md": "Current source version: 0.32.4.",
|
||||
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.32.4",
|
||||
"README.md": "# RustProxy 0.32.5",
|
||||
"CHANGELOG.md": "## 0.32.5",
|
||||
"ROADMAP.md": "## 0.32.5",
|
||||
"AGENTS.md": "Current source version: 0.32.5.",
|
||||
"docs/TEST_REPORT.md": "# Verification report - RustProxy 0.32.5",
|
||||
}.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"
|
||||
@@ -285,7 +285,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.32.4"', '"/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.32.5"', '"/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
|
||||
@@ -1396,7 +1396,7 @@ 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.32.4"' in openapi
|
||||
assert '"RuntimeInformation"' in openapi and '"version": "0.32.5"' in openapi
|
||||
|
||||
# 0.24.1 compiler and hostname-cardinality regressions.
|
||||
tls_0241 = rust_source(root, "src/tls.rs")
|
||||
|
||||
@@ -14,7 +14,7 @@ parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--require-lock', action='store_true', help='Require the post-upgrade Cargo.lock produced by cargo update')
|
||||
args = parser.parse_args()
|
||||
manifest = tomllib.loads((ROOT / 'Cargo.toml').read_text())
|
||||
assert manifest['package']['version'] == '0.32.4'
|
||||
assert manifest['package']['version'] == '0.32.5'
|
||||
assert manifest['package']['rust-version'] == '1.99'
|
||||
deps = manifest['dependencies']
|
||||
expected_requirements = {
|
||||
|
||||
@@ -51,7 +51,7 @@ assert '"/docs/content.json"' in admin
|
||||
readme = (ROOT / "README.md").read_text(encoding="utf-8")
|
||||
roadmap = (ROOT / "ROADMAP.md").read_text(encoding="utf-8")
|
||||
changelog = (ROOT / "CHANGELOG.md").read_text(encoding="utf-8")
|
||||
assert readme.startswith("# RustProxy 0.32.4")
|
||||
assert readme.startswith("# RustProxy 0.32.5")
|
||||
assert "docs/WEB_SERVER.md" in readme and "docs/README.md" in readme
|
||||
assert readme.count("## What changed in ") == 1, "README duplicates historical release notes; use CHANGELOG/archive"
|
||||
assert "## Release history" in readme and "docs/ROADMAP_HISTORY.md" in readme
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Static source contract for DDNS ACL 0.32.5; NOT a Rust test."""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import tomllib
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
read = lambda p: (ROOT / p).read_text(encoding="utf-8")
|
||||
acl = read('src/acl.rs')
|
||||
dns = read('src/acl/dynamic.rs')
|
||||
js = read('src/admin/web/management.js')
|
||||
checks = {
|
||||
'keep static IP/CIDR checks': 'RuleMatch::Ip(net) => net.contains(&peer)' in acl,
|
||||
'dynamic DNS only allows explicit allow rules': 'dynamic DNS ACL rules only support allow' in acl,
|
||||
'deny precedence retained': 'return Some(Action::Deny)' in acl,
|
||||
'strict hostname validation': 'pub(crate) fn hostname(' in dns,
|
||||
'scope scan covers vhosts, locations, profiles, host policies and docker': all(f in dns for f in [
|
||||
'config.host_policies', 'config.acl_profiles', 'config.vhosts', 'vhost.routes', 'config.docker_agents.agents', 'agent.assignments'
|
||||
]),
|
||||
'bounded asynchronous DNS work': all(x in dns for x in ['REFRESH_SECONDS: u64 = 60', 'MAX_AGE_SECONDS: u64 = 180', 'MAX_NAMES: usize = 128', 'MAX_ADDRESSES: usize = 32', 'PARALLEL_LOOKUPS: usize = 8', 'LOOKUP_SECONDS: u64 = 4', 'buffer_unordered(PARALLEL_LOOKUPS)']),
|
||||
'lookup on refresh, not on request': 'lookup_host' in dns and 'lookup_host' not in acl and 'dynamic::matches' in acl,
|
||||
'fail closed on empty or failed resolution': 'CACHE.store(Arc::new(results))' in dns and 'return (name, None);' in dns and 'entry.valid_until > Instant::now()' in dns,
|
||||
'update after configuration commit': all('crate::acl::dynamic::config_changed()' in read(p) for p in ['src/runtime/updates.rs', 'src/runtime/docker.rs', 'src/runtime/certificates.rs']),
|
||||
'startup background refresh': 'state.start_dns_acl_updates();' in read('src/main/admin_runtime.rs'),
|
||||
'visual selector and disabled DNS deny': '.acl-profile-rule-type' in js and 'aclDnsAllowOnly' in js,
|
||||
'old network field persisted': 'network: normalizeNetwork(' in js,
|
||||
'PL/EN translations': all(k in json.loads(read(f'langs/{loc}.json'))['translations'] for loc in ('en_US','pl_pl') for k in ('aclRuleType','aclRuleDns','aclDnsHelp','aclDnsAllowOnly')),
|
||||
'package version': tomllib.loads(read('Cargo.toml'))['package']['version'] == '0.32.5',
|
||||
}
|
||||
for name, ok in checks.items():
|
||||
if not ok: raise AssertionError(name)
|
||||
print(f'PASS: {len(checks)} DNS ACL 0.32.5 static source checks (not compiled or network-tested)')
|
||||
@@ -4,7 +4,7 @@ from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
html = (ROOT / 'src/admin/web/index.html').read_text()
|
||||
assert '0.32.4' in (ROOT / "Cargo.toml").read_text()
|
||||
assert '0.32.5' in (ROOT / "Cargo.toml").read_text()
|
||||
assert '<a class="brand" href="/"' in html, 'logo must remain a true full-page navigation'
|
||||
assert 'addEventListener("click"' not in html.split('<a class="brand" href="/"',1)[1].split('</a>',1)[0]
|
||||
body = (ROOT / 'src/proxy/cache_helpers.rs').read_text()
|
||||
|
||||
@@ -51,6 +51,6 @@ for marker in ['margin: 0;', '--overview-gap: max(3px, calc(var(--ui-gap) - 1px)
|
||||
retry = re.search(r'fn retry_request\([\s\S]*?\n}\n', proxy)
|
||||
assert retry and '.uri(uri.clone())' in retry[0]
|
||||
assert 'upstream_request_target(&uri, request.headers_mut()' in retry[0]
|
||||
assert json.loads(read('src/admin/openapi.json'))['info']['version']=='0.32.4'
|
||||
assert 'version = "0.32.4"' in read('Cargo.toml')
|
||||
print('PASS: 0.32.4 origin pinning, authority, retry, CSS gutter source contracts (not Rust runtime)')
|
||||
assert json.loads(read('src/admin/openapi.json'))['info']['version']=='0.32.5'
|
||||
assert 'version = "0.32.5"' in read('Cargo.toml')
|
||||
print('PASS: 0.32.5 origin pinning, authority, retry, CSS gutter source contracts (not Rust runtime)')
|
||||
@@ -8,9 +8,9 @@ from html.parser import HTMLParser
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
def read(rel): return (ROOT / rel).read_text(encoding='utf-8')
|
||||
assert tomllib.loads(read('Cargo.toml'))['package']['version'] == '0.32.4'
|
||||
assert 'name = "rust-proxy"\nversion = "0.32.4"' in read('Cargo.lock')
|
||||
assert json.loads(read('src/admin/openapi.json'))['info']['version'] == '0.32.4'
|
||||
assert tomllib.loads(read('Cargo.toml'))['package']['version'] == '0.32.5'
|
||||
assert 'name = "rust-proxy"\nversion = "0.32.5"' in read('Cargo.lock')
|
||||
assert json.loads(read('src/admin/openapi.json'))['info']['version'] == '0.32.5'
|
||||
|
||||
pages = read('src/pages.rs')
|
||||
for code in (400, 401, 403, 404, 408, 410, 413, 429, 500, 502, 503, 504):
|
||||
|
||||
@@ -135,7 +135,7 @@ def upgrade_smoke(tmp: Path) -> None:
|
||||
assert backup.is_dir()
|
||||
assert (backup / "src/obsolete.rs").is_file()
|
||||
assert not (target / "src/obsolete.rs").exists()
|
||||
assert 'version = "0.32.4"' in (target / "Cargo.toml").read_text(encoding="utf-8")
|
||||
assert 'version = "0.32.5"' in (target / "Cargo.toml").read_text(encoding="utf-8")
|
||||
assert (target / "data/keep.txt").read_text(encoding="utf-8") == "preserve\n"
|
||||
assert (target / ".env").read_text(encoding="utf-8") == "RUST_PROXY_DEMO=0\n"
|
||||
assert (target / "langs/site.json").is_file()
|
||||
@@ -146,7 +146,7 @@ def upgrade_smoke(tmp: Path) -> None:
|
||||
assert (target / "docker-agent/certificate.go").is_file()
|
||||
assert (target / "docker-agent/server.go").is_file()
|
||||
manifest = json.loads((backup / "upgrade.json").read_text(encoding="utf-8"))
|
||||
assert manifest["to_version"] == "0.32.4"
|
||||
assert manifest["to_version"] == "0.32.5"
|
||||
assert manifest["removed_obsolete_runtime_state"] is True
|
||||
assert not legacy.exists()
|
||||
assert not (backup / "legacy-data").exists()
|
||||
@@ -617,7 +617,7 @@ def source_contract_smoke() -> None:
|
||||
assert marker in admin, marker
|
||||
anonymous_block = admin.split("fn anonymous_allowed", 1)[1].split("const CERTIFICATE_API_KEY_HEADER", 1)[0]
|
||||
assert '"/api/status"' not in anonymous_block
|
||||
assert '"RuntimeInformation"' in openapi_0241 and '"version": "0.32.4"' in openapi_0241
|
||||
assert '"RuntimeInformation"' in openapi_0241 and '"version": "0.32.5"' in openapi_0241
|
||||
assert 'id="panel-logging"' not in html
|
||||
for marker in ['id="settings-tab-logging"', 'id="settings-page-logging"', 'id="logging-form"', 'id="error-log-form"']:
|
||||
assert marker in html, marker
|
||||
@@ -1102,7 +1102,7 @@ def source_contract_smoke() -> None:
|
||||
assert '.managed-update' in main and "flush_hot_to_cold_for_update" in main
|
||||
openapi = (ROOT / "src/admin/openapi.json").read_text(encoding="utf-8")
|
||||
assert '"/api/config/history/restore"' in openapi
|
||||
for marker in ['"version": "0.32.4"', '"memory_preset"', '"cold_preset"', '"memory_budget_bytes"', '"max_inflight"', '"preset"', '"session_days"', '"session_lifetime_seconds"', '"accept_local_listener_risk"', '"backend_header"', '"backend_timing_header"', '"cold_on_age"', '"match_type"', '"regex_insensitive"', '"NotFoundHost"', '"not_found_hosts"', '"PrometheusSettings"', '"allow_trusted_network_without_token"', '"include_docker_vhosts"', '"include_streams"', '"include_logging"']:
|
||||
for marker in ['"version": "0.32.5"', '"memory_preset"', '"cold_preset"', '"memory_budget_bytes"', '"max_inflight"', '"preset"', '"session_days"', '"session_lifetime_seconds"', '"accept_local_listener_risk"', '"backend_header"', '"backend_timing_header"', '"cold_on_age"', '"match_type"', '"regex_insensitive"', '"NotFoundHost"', '"not_found_hosts"', '"PrometheusSettings"', '"allow_trusted_network_without_token"', '"include_docker_vhosts"', '"include_streams"', '"include_logging"']:
|
||||
assert marker in openapi, marker
|
||||
assert '"software_update"' in openapi and '"update_available"' in openapi
|
||||
for marker in ['"/api/certificates/deploy"', '"CertificateDeploy"', '"CertificateDeployResult"', '"/api/certificates/reload"']:
|
||||
|
||||
@@ -21,7 +21,7 @@ const openapi = json('src/admin/openapi.json');
|
||||
const en = json('langs/en_US.json').translations;
|
||||
const pl = json('langs/pl_pl.json').translations;
|
||||
|
||||
assert.match(manifest, /version = "0\.32\.4"/);
|
||||
assert.match(manifest, /version = "0\.32\.5"/);
|
||||
assert.match(lib, /pub mod user_agent;/);
|
||||
assert.match(model, /user_agent_blocking: crate::user_agent::Policy/);
|
||||
assert.match(vhost, /user_agent_blocking: crate::user_agent::Policy/);
|
||||
@@ -52,7 +52,7 @@ assert.match(fileLogs, /localStorage\.setItem\(CONSOLIDATION_STORAGE_KEY/);
|
||||
assert.match(fileLogs, /aggregate_min_count/);
|
||||
assert.match(fileLogs, /file-log-aggregate-copy/);
|
||||
|
||||
assert.equal(openapi.info.version, '0.32.4');
|
||||
assert.equal(openapi.info.version, '0.32.5');
|
||||
assert.ok(openapi.components.schemas.Config.properties.user_agent_blocking);
|
||||
assert.ok(openapi.components.schemas.Vhost.properties.user_agent_blocking);
|
||||
assert.ok(openapi.components.schemas.FileLogSource.properties.group_id);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Offline source contracts for RustProxy 0.32.4 upstream protocols and card registry.
|
||||
"""Offline source contracts for RustProxy 0.32.5 upstream protocols and card registry.
|
||||
|
||||
These assertions supplement, rather than replace, Rust ALPN, H2C and websocket
|
||||
runtime tests. No code execution against a RustProxy server is implied.
|
||||
@@ -141,7 +141,7 @@ for field in ('dashboard_widgets', 'dashboard_hidden_widgets'):
|
||||
|
||||
|
||||
|
||||
assert '"version": "0.32.4"' in read('src/admin/openapi.json')
|
||||
assert 'version = "0.32.4"' in read('Cargo.toml')
|
||||
assert 'version = "0.32.4"' in read('Cargo.lock')
|
||||
print(f'PASS: 0.32.4 upstream H1/Auto/compatible-HTTP2/strict-H2 source contracts and {len(ids)} registered Overview Cards')
|
||||
assert '"version": "0.32.5"' in read('src/admin/openapi.json')
|
||||
assert 'version = "0.32.5"' in read('Cargo.toml')
|
||||
assert 'version = "0.32.5"' in read('Cargo.lock')
|
||||
print(f'PASS: 0.32.5 upstream H1/Auto/compatible-HTTP2/strict-H2 source contracts and {len(ids)} registered Overview Cards')
|
||||
Reference in new issue
Block a user