feat(v1): harden typed runtime boundaries
Elect one canonical EffectBatch codec, remove the parallel postcard API, and strengthen fail-closed host, form, sync, WASM, macro, generated-contract, and test-harness proofs with mutation-driven coverage. req: wire/008 req: wire/009 req: wire/010 req: push/008 req: client_local/015 req: client_local/016 req: client_local/017 req: client_local/018 req: client_local/019 req: sync/024 req: sync/025 req: sync/026 req: sync/027 req: sync/028 req: sync/029 req: test/020 req: test/021
This commit is contained in:
+98
-2
@@ -34,8 +34,8 @@ pub struct ClientState {
|
||||
|
||||
/// Validates primitive wasm-bindgen values before application code runs.
|
||||
///
|
||||
/// Primitive arguments keep JavaScript from owning a second binary codec. The
|
||||
/// ordinary effect result remains postcard-encoded by `hemx-core`.
|
||||
/// Primitive arguments keep JavaScript from owning a second event/state codec.
|
||||
/// The ordinary effect result uses `hemx-core`'s canonical `EffectBatch` codec.
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn decode_client_inputs(
|
||||
@@ -149,6 +149,102 @@ mod tests {
|
||||
); // req: client_local/008
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_input_boundary_accepts_limits_and_preserves_values() {
|
||||
let kind = "k".repeat(256);
|
||||
let value = "v".repeat(64 * 1024);
|
||||
let key = "x".repeat(1024);
|
||||
let state = "s".repeat(1024 * 1024);
|
||||
|
||||
let (event, decoded_state) = decode_client_inputs(
|
||||
1,
|
||||
kind.clone(),
|
||||
Some(value.clone()),
|
||||
Some(true),
|
||||
Some(key.clone()),
|
||||
1,
|
||||
state.clone(),
|
||||
)
|
||||
.expect("documented client-local limits are inclusive");
|
||||
|
||||
assert_eq!(
|
||||
event,
|
||||
ClientEvent {
|
||||
kind,
|
||||
value: Some(value),
|
||||
checked: Some(true),
|
||||
key: Some(key),
|
||||
}
|
||||
);
|
||||
assert_eq!(decoded_state, ClientState { encoded: state });
|
||||
// req: client_local/005 test req: client_local/015 test req: client_local/016 test req: client_local/017 test req: client_local/018 test req: client_local/019 test
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_input_boundary_rejects_invalid_versions_and_payload_sizes() {
|
||||
let decode = |event_version, kind, value, key, state_version, state| {
|
||||
decode_client_inputs(event_version, kind, value, None, key, state_version, state)
|
||||
};
|
||||
|
||||
for (result, expected) in [
|
||||
(
|
||||
decode(0, "click".into(), None, None, 1, String::new()),
|
||||
"unsupported client-local event ABI version 0; expected 1",
|
||||
),
|
||||
(
|
||||
decode(1, String::new(), None, None, 1, String::new()),
|
||||
"invalid client-local event payload: event kind must contain 1..=256 bytes",
|
||||
),
|
||||
(
|
||||
decode(1, "k".repeat(257), None, None, 1, String::new()),
|
||||
"invalid client-local event payload: event kind must contain 1..=256 bytes",
|
||||
),
|
||||
(
|
||||
decode(
|
||||
1,
|
||||
"input".into(),
|
||||
Some("v".repeat(64 * 1024 + 1)),
|
||||
None,
|
||||
1,
|
||||
String::new(),
|
||||
),
|
||||
"invalid client-local event payload: value exceeds 65536 bytes",
|
||||
),
|
||||
(
|
||||
decode(
|
||||
1,
|
||||
"keydown".into(),
|
||||
None,
|
||||
Some("k".repeat(1025)),
|
||||
1,
|
||||
String::new(),
|
||||
),
|
||||
"invalid client-local event payload: key exceeds 1024 bytes",
|
||||
),
|
||||
(
|
||||
decode(1, "click".into(), None, None, 0, String::new()),
|
||||
"unsupported client-local state ABI version 0; expected 1",
|
||||
),
|
||||
(
|
||||
decode(
|
||||
1,
|
||||
"click".into(),
|
||||
None,
|
||||
None,
|
||||
1,
|
||||
"s".repeat(1024 * 1024 + 1),
|
||||
),
|
||||
"invalid client-local state payload: state exceeds 1048576 bytes",
|
||||
),
|
||||
] {
|
||||
assert_eq!(
|
||||
result.expect_err("invalid client input must fail closed"),
|
||||
expected
|
||||
);
|
||||
}
|
||||
// req: client_local/008 test req: client_local/015 test req: client_local/016 test req: client_local/017 test req: client_local/018 test req: client_local/019 test
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_handler_uses_the_ordinary_effect_wire_format() {
|
||||
let fingerprint = BuildFingerprint(17);
|
||||
|
||||
Reference in New Issue
Block a user