Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/rules/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Only documented format: original **dae syntax**, `{ include { ... } global { ...
- VLESS permits UDP/443 by default, including base Vision; users block QUIC through routing. Xray `Udp443Policy` defaults to `Allow`, while explicit `Reject` and UDP-disabled remain terminal. `Skip` selects protocol fallback without an implicit Vision port gate. Normalize the `xtls-rprx-vision-udp443` input spelling to base Vision before identity/runtime reuse; never let that spelling override explicit packet policy.
- VLESS `vless_mode` has been removed: reject its raw presence, including `null`, rather than interpreting an alias. Static entries reject the candidate config; subscriptions salvage other valid entries, but an all-old-mode cached body cannot restore offline. The same flat field on a non-VLESS serde record remains only a compatibility artifact; do not change VMess behavior or identity through VLESS cleanup. Normalize before `Node::derive_id`; every admitted VLESS node is re-derived with a new ID at this upgrade, not only nodes with an explicit old mode. Name-based persisted Selector choices and valid TCP-v4 delays no older than 24 hours can survive; delay restoration is not liveness restoration.
- Share-link VLESS failures carry `DetailedConfigError` from their origin; schema fields and safe reasons are not reconstructed from legacy prose. Public legacy APIs project only at the exit. `node/wire.rs` derives flat serialization from its complete borrowed output view; input raw-presence validation remains separate.
- A share link that parses warns only with `legacy-*` codes; `Node::parse_share_link` debug-asserts it at its single warning sink. Native clients validate one `node {}` declaration in `syntax` mode and read any other warning as a dropped entry, so a new warning for an accepted link needs a `legacy-*` code. `source_edit` managed entries carry the static parser or admission reason in `SourceEditError.reason`; native node/provider creation returns it as `error.message`, never a submitted value.
- VLESS identity separates plaintext from TLS while keeping REALITY's effective transport independent of a redundant TLS flag. Share-link `security`/`tls` claims coalesce only when equal and reject contradictions. VLESS and Trojan map REALITY intent through shared TLS options; unsupported share-link schemes reject that intent instead of silently using ordinary TLS.
- Shared XHTTP configuration, strict typed Xray extras and flat serde glue live in `node/xhttp.rs` through `StreamTransportOptions.xhttp`; `share_link/xhttp.rs` owns URI/VMess XHTTP claims. XHTTP-aware adapters use `options/vocab::xhttp_stream_transport`, while legacy records/sing-box use `stream_transport`. URI/VMess/flat/Mihomo adapters normalize paths, headers, ranges and H2 ALPN before identity; immutable admission rejects noncanonical direct nodes through the shared stream/TLS checks. Only XHTTP IDs add accepted request/pacing options and effective TLS posture; old transport IDs remain unchanged. Supported extra fields are strict, duplicate-aware and value-redacted. Xray-shaped `downloadSettings` (URI/VMess) and panel `download-settings` (Clash) share `XrayDownload` into `XhttpOptions.download` without inheritance, and admission validates the TLS-only `Node::xhttp_download_view`; XMUX passes only all-zero or at Xray's implicit defaults, and server-only options are type-checked and dropped. Other unsupported placement fields reject by raw presence, never by whether a value looks active. Official sing-box and client-record XHTTP remain unsupported. See the bilingual node reference for the H2 profile and bounds.

Expand Down
16 changes: 8 additions & 8 deletions crates/honk-config/conformance/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ reason = "honk accepts its documented dialect; the pinned dae parser rejects thi

[[case]]
id = "honk-doc-en-reference-nodes-02"
source = { file = "doc/en/reference/nodes.md", lines = "181-184" }
source = { file = "doc/en/reference/nodes.md", lines = "183-186" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -1777,7 +1777,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-en-reference-nodes-03"
source = { file = "doc/en/reference/nodes.md", lines = "271-273" }
source = { file = "doc/en/reference/nodes.md", lines = "273-275" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -1788,7 +1788,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-en-reference-nodes-04"
source = { file = "doc/en/reference/nodes.md", lines = "324-329" }
source = { file = "doc/en/reference/nodes.md", lines = "326-331" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -1799,7 +1799,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-en-reference-nodes-05"
source = { file = "doc/en/reference/nodes.md", lines = "204-206" }
source = { file = "doc/en/reference/nodes.md", lines = "206-208" }
wrap = ""
layer = "structure"
honk = "accept"
Expand Down Expand Up @@ -2083,7 +2083,7 @@ reason = "honk accepts its documented dialect; the pinned dae parser rejects thi

[[case]]
id = "honk-doc-zh-reference-nodes-02"
source = { file = "doc/zh/reference/nodes.md", lines = "180-183" }
source = { file = "doc/zh/reference/nodes.md", lines = "182-185" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -2094,7 +2094,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-zh-reference-nodes-03"
source = { file = "doc/zh/reference/nodes.md", lines = "270-272" }
source = { file = "doc/zh/reference/nodes.md", lines = "272-274" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -2105,7 +2105,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-zh-reference-nodes-04"
source = { file = "doc/zh/reference/nodes.md", lines = "323-328" }
source = { file = "doc/zh/reference/nodes.md", lines = "325-330" }
wrap = ""
layer = "structure"
honk = "accept"
Expand All @@ -2116,7 +2116,7 @@ unknown_sections = 0

[[case]]
id = "honk-doc-zh-reference-nodes-05"
source = { file = "doc/zh/reference/nodes.md", lines = "203-205" }
source = { file = "doc/zh/reference/nodes.md", lines = "205-207" }
wrap = ""
layer = "structure"
honk = "accept"
Expand Down
25 changes: 20 additions & 5 deletions crates/honk-config/src/node/xhttp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,13 +568,28 @@ impl XhttpOptions {

/// Validate canonical options for immutable node admission.
pub fn validate(&self) -> Result<(), &'static str> {
for (range, min, max) in [
(self.x_padding_bytes, 1, 8192),
(self.sc_max_each_post_bytes, 1, 16 * 1024 * 1024),
(self.sc_min_posts_interval_ms, 0, 60_000),
for (range, min, max, error) in [
(
self.x_padding_bytes,
1,
8192,
"XHTTP xPaddingBytes must stay within 1-8192",
),
(
self.sc_max_each_post_bytes,
1,
16 * 1024 * 1024,
"XHTTP scMaxEachPostBytes must stay within 1-16777216",
),
(
self.sc_min_posts_interval_ms,
0,
60_000,
"XHTTP scMinPostsIntervalMs must stay within 0-60000",
),
] {
if range.min < min || range.min > range.max || range.max > max {
return Err("XHTTP range exceeds supported bounds");
return Err(error);
}
}
let path = self
Expand Down
Loading