hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

commit 2c421b37ae844fddc711727d898e27a0131d4c43
parent 0b18b5409e507b1769a0e5b15073769fb194c8b6
Author: triesap <tyson@radroots.org>
Date:   Wed, 23 Sep 2026 14:12:25 +0000

test(hyf): characterize jev authentication wiring

- Extend the loopback Jev fixture with a header-capture mode that reports captured header names only, so characterization never needs a real credential.
- Characterize the current wiring: the Jev client reaches the intended origin without an Authorization header, and the fixture convenience modes report no Bearer requirement.
- Characterize the target: the intended origin rejects an exchange that has no Bearer header and accepts the sentinel token, which is the assertion the later implementation step flips.
- Keep the baseline green (19/19) with no skipped security test and no product src/schema/dependency/lock change.

Diffstat:
Mtests/jev_provider_helper.mojo | 29+++++++++++++++++++++++++++++
Mtests/test_jev.mojo | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 159 insertions(+), 0 deletions(-)

diff --git a/tests/jev_provider_helper.mojo b/tests/jev_provider_helper.mojo @@ -32,6 +32,7 @@ from parent_lifecycle import ( ) from strict_fixture import ( STRICT_MAX_REPORT_BYTES, + json_escape, STRICT_COMPLETION_GRACE_MS, ConnectionReader, ExchangeScript, @@ -113,6 +114,29 @@ def _delay_ms(mode: String) -> Int: return 0 +def header_names_json(headers_raw: String) -> String: + """Captured request header *names* as a JSON array, values redacted. + + H006 characterization: the loopback fixture can report which headers it + captured without ever embedding a real or sentinel credential value. + """ + var out = String("[") + var first = True + for line in headers_raw.split("\r\n"): + var entry = String(line) + var colon = entry.find(":") + if colon <= 0: + continue + var name = String(entry[byte=0:colon]).strip().lower() + if name == "": + continue + if not first: + out += "," + out += json_escape(name) + first = False + return out + "]" + + def _body(mode: String) -> String: if mode == "ok" or mode == "slow": return analysis() @@ -141,6 +165,11 @@ def _build_script(mode: String, framed: FramedRequest) -> ExchangeScript: var raw = _raw_response(mode) if raw != "": script.raw_response = raw + elif mode == "echo_headers": + # Header capture with values redacted: only names are echoed. + script.response_body = ( + '{"captured_headers":' + header_names_json(framed.headers_raw) + "}" + ) elif mode == "echo_authorization": var auth = authorization_reason(framed.headers_raw, True) if auth != "": diff --git a/tests/test_jev.mojo b/tests/test_jev.mojo @@ -452,3 +452,133 @@ def test_transport_cleanup_and_local_cancellation() raises: ) guard_7.assert_clean() + + +from flare.net import SocketAddr +from flare.tcp import TcpStream +from jev_provider_helper import ( + header_names_json, + require_bearer_for, + spawn_jev_scripted_auto, +) +from strict_fixture import ExchangeScript, exchange_script + + +def _raw_jev_exchange(port: Int, raw: String) raises -> String: + var client = TcpStream.connect(SocketAddr.localhost(UInt16(port))) + client.write_all(Span[UInt8, _](raw.as_bytes())) + var response = String("") + var buffer = InlineArray[Byte, 4096](fill=0) + while True: + var n = client.read(buffer.unsafe_ptr(), 4096) + if n <= 0: + break + response += String( + unsafe_from_utf8=Span(ptr=buffer.unsafe_ptr(), length=Int(n)) + ) + client.close() + return response^ + + +def test_jev_fixture_captures_headers_without_leaking_a_secret() raises: + # H006: the loopback Jev fixture captures request headers and reports only + # the captured *names*, so characterization never needs a real credential. + assert_equal( + header_names_json( + "host: h\r\nx-sentinel: v\r\nauthorization: Bearer t" + ), + '["host","x-sentinel","authorization"]', + ) + var guard = CleanupGuard() + with spawn_jev_stub_auto("echo_headers", 1, guard) as started: + var response = _raw_jev_exchange( + started.port, + ( + "POST /v1/systemone HTTP/1.1\r\nhost: 127.0.0.1\r\n" + "x-sentinel: value\r\nauthorization: Bearer" + " hyf-sentinel-token\r\ncontent-length: 2\r\n" + "connection: close\r\n\r\n{}" + ), + ) + assert_true(response.find('"x-sentinel"') >= 0) + assert_true(response.find('"authorization"') >= 0) + # Redaction baseline: names only, never the credential value. + assert_true(response.find("hyf-sentinel-token") < 0) + started.stub.wait() + guard.assert_clean() + + +def test_jev_provider_wiring_sends_no_authorization_today() raises: + # H006: characterize the current absence. The Jev client reaches the + # intended origin today without an Authorization header; this test is green + # by design and documents exactly what the later implementation step flips. + var guard = CleanupGuard() + with spawn_jev_stub_auto("echo_headers", 1, guard) as started: + var outcome = post_jev_systemone( + "http://127.0.0.1:" + String(started.port), + _loads('{"model":"jev-1.13.0","state":"s","questions":{}}'), + 5000, + ) + assert_equal(outcome.status, 200) + assert_true(outcome.body_text.find('"captured_headers"') >= 0) + # Current gap: no credential header is sent or captured. + assert_true(outcome.body_text.find('"authorization"') < 0) + assert_true(outcome.body_text.find('"x-sentinel"') < 0) + started.stub.wait() + guard.assert_clean() + + +def test_jev_target_requires_bearer_header_characterization() raises: + # H006: the target behavior for the intended origin is that a Bearer header + # is required. Turning this on for the real wiring is the later step's + # change; the sentinel value is the only credential used here. + var guard = CleanupGuard() + var scripts = List[ExchangeScript]() + var script = exchange_script( + "target_auth", "POST", "/v1/systemone", 200, '{"ok":true}' + ) + script.require_bearer = True + scripts.append(script^) + with spawn_jev_scripted_auto(scripts^, guard) as started: + # The intended origin refuses the exchange before answering: the + # fixture records the exact rejection reason instead of returning 200. + _ = _raw_jev_exchange( + started.port, + ( + "POST /v1/systemone HTTP/1.1\r\nhost: 127.0.0.1\r\n" + "content-length: 2\r\nconnection: close\r\n\r\n{}" + ), + ) + started.stub.reap() + assert_equal(started.stub.phase(), "exchange") + assert_equal(started.stub.reason(), "auth_missing") + guard.assert_clean() + + var accepted_guard = CleanupGuard() + var accepted_scripts = List[ExchangeScript]() + var accepted_script = exchange_script( + "target_auth_ok", "POST", "/v1/systemone", 200, '{"ok":true}' + ) + accepted_script.require_bearer = True + accepted_scripts.append(accepted_script^) + with spawn_jev_scripted_auto( + accepted_scripts^, accepted_guard + ) as ok_started: + var accepted = _raw_jev_exchange( + ok_started.port, + ( + "POST /v1/systemone HTTP/1.1\r\nhost: 127.0.0.1\r\n" + "authorization: Bearer hyf-sentinel-token\r\n" + "content-length: 2\r\nconnection: close\r\n\r\n{}" + ), + ) + assert_true(accepted.find("200") >= 0) + ok_started.stub.wait() + accepted_guard.assert_clean() + + +def test_jev_require_bearer_target_is_characterized_off() raises: + # H006: the fixture's convenience modes still report no Bearer requirement, + # which is the characterization surface the later step flips. + assert_true(not require_bearer_for("ok")) + assert_true(not require_bearer_for("echo_headers"))