Skip to content

Commit b370f3c

Browse files
committed
Complete runnable VCL-style cache policy example
1 parent b465854 commit b370f3c

9 files changed

Lines changed: 69 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ behavior when the change improves security or project direction.
2121
- Add the checked-in HAProxy Lua/SPOE-style symbolic route policy and config
2222
example, with live canary, load-balancer, persistence, mirror, and selected
2323
route-policy coverage.
24+
- Complete the VCL-like cache-policy example gate with schema validation and
25+
live pass, variant, TTL, metadata, tag-purge, and negative mutation coverage.
2426

2527
### Security
2628

crates/fluxheim-config/src/config_tests_wasm.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ fn haproxy_spoe_routing_policy_example_config_validates() {
6666
assert_eq!(config.validate(), Ok(()));
6767
}
6868

69+
#[cfg(feature = "wasm")]
70+
#[test]
71+
fn vcl_cache_policy_example_config_validates() {
72+
let config: Config =
73+
toml::from_str(include_str!("../../../examples/wasm/cache-policy.toml")).unwrap();
74+
75+
assert_eq!(config.validate(), Ok(()));
76+
}
77+
6978
#[cfg(feature = "wasm")]
7079
fn proxy_preview_wasm_config(plugin_fields: &str) -> Config {
7180
toml::from_str(&format!(

crates/fluxheim-server/src/native_http1_route_proxy_tests/wasm.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,27 +1310,35 @@ async fn native_wasm_cache_policy_example_matches_documented_behavior() {
13101310
("/static/example.png", "mobile-body"),
13111311
("/static/example.png", "desktop-body"),
13121312
("/static/example.png", "mobile-refill"),
1313+
("/static/example.png", "mobile-after-tag-purge"),
13131314
])
13141315
.await;
13151316
let mut config = fixture.config_with_attachments(
13161317
upstream,
13171318
vec![
13181319
wasm_attachment_phase(
13191320
"cache_lookup",
1320-
"route",
1321+
"vcl-static",
13211322
100,
13221323
fluxheim_config::WasmPluginPhase::CacheLookup,
13231324
),
13241325
wasm_attachment_phase(
13251326
"cache_store",
1326-
"route",
1327+
"vcl-static",
13271328
100,
13281329
fluxheim_config::WasmPluginPhase::CacheStore,
13291330
),
13301331
],
13311332
);
13321333
config.vhosts[0].routes[0].path_exact = None;
13331334
config.vhosts[0].routes[0].path_prefix = Some("/".to_owned());
1335+
config.vhosts[0].name = "vcl.test".to_owned();
1336+
config.vhosts[0].hosts = vec!["vcl.test".to_owned()];
1337+
config.vhosts[0].routes[0].name = "vcl-static".to_owned();
1338+
config.server.default_vhost = Some("vcl.test".to_owned());
1339+
for attachment in &mut config.wasm.attachments {
1340+
attachment.vhost = "vcl.test".to_owned();
1341+
}
13341342
config.vhosts[0].routes[0].redirect = None;
13351343
config.vhosts[0].routes[0].proxy = Some(fluxheim_config::ProxyConfig {
13361344
upstreams: vec![upstream.to_string()],
@@ -1343,23 +1351,23 @@ async fn native_wasm_cache_policy_example_matches_documented_behavior() {
13431351

13441352
let mobile = downstream_request(
13451353
proxy,
1346-
"GET /static/example.png HTTP/1.1\r\nHost: route.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
1354+
"GET /static/example.png HTTP/1.1\r\nHost: vcl.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
13471355
)
13481356
.await;
13491357
let desktop = downstream_request(
13501358
proxy,
1351-
"GET /static/example.png HTTP/1.1\r\nHost: route.test\r\nX-Device-Class: desktop\r\nConnection: close\r\n\r\n",
1359+
"GET /static/example.png HTTP/1.1\r\nHost: vcl.test\r\nX-Device-Class: desktop\r\nConnection: close\r\n\r\n",
13521360
)
13531361
.await;
13541362
let mobile_hit = downstream_request(
13551363
proxy,
1356-
"GET /static/example.png HTTP/1.1\r\nHost: route.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
1364+
"GET /static/example.png HTTP/1.1\r\nHost: vcl.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
13571365
)
13581366
.await;
13591367
tokio::time::sleep(Duration::from_millis(1200)).await;
13601368
let mobile_expired = downstream_request(
13611369
proxy,
1362-
"GET /static/example.png HTTP/1.1\r\nHost: route.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
1370+
"GET /static/example.png HTTP/1.1\r\nHost: vcl.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
13631371
)
13641372
.await;
13651373

@@ -1407,6 +1415,27 @@ async fn native_wasm_cache_policy_example_matches_documented_behavior() {
14071415
response_header(&mobile_expired, "x-cache-status").as_deref(),
14081416
Some("MISS")
14091417
);
1418+
1419+
let purged = crate::purge_native_memory_cache_tag(
1420+
"vcl.test",
1421+
Some("vcl-static"),
1422+
"vcl.test:route:vcl-static",
1423+
"wasm-policy",
1424+
16,
1425+
false,
1426+
);
1427+
assert_eq!(purged.matched, 2);
1428+
assert_eq!(purged.purged, 2);
1429+
let after_purge = downstream_request(
1430+
proxy,
1431+
"GET /static/example.png HTTP/1.1\r\nHost: vcl.test\r\nX-Device-Class: mobile\r\nConnection: close\r\n\r\n",
1432+
)
1433+
.await;
1434+
assert!(after_purge.ends_with("mobile-after-tag-purge"));
1435+
assert_eq!(
1436+
response_header(&after_purge, "x-cache-status").as_deref(),
1437+
Some("MISS")
1438+
);
14101439
}
14111440

14121441
#[tokio::test]

docs/wasm-policy-example-parity.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ checked-in `examples/wasm/cache-lookup-policy.wat` and
179179
native HTTP/1 test suite compiles the example sources directly. Richer
180180
store-admission mutation remains follow-up `1.7.x` cache-policy work.
181181

182+
For `v1.7.9`, the example TOML is schema-validated and the shared live policy
183+
smoke proves pass versus MISS/HIT behavior, bounded device-class variants,
184+
image-only TTL/tag/stored-header mutation, TTL expiry, non-image isolation,
185+
tag-based purge through Fluxheim's cache tooling, and fail-closed unknown or
186+
duplicate mutation IDs. This is typed VCL-like capability parity; it does not
187+
embed VCL or expose raw cache objects.
188+
182189
## Stabilization Requirements
183190

184191
Before `1.7` is complete:

examples/wasm/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ uses fixed Fluxheim host-call IDs. Plugins cannot emit arbitrary cache-key
5959
bytes, TTLs, tags, response headers, upstream targets, or filesystem paths
6060
through this ABI.
6161

62+
Together, these files are the VCL-like cache-policy migration example. The
63+
live example smoke proves cache pass versus MISS/HIT behavior, bounded
64+
mobile/desktop key variants, image-only TTL/tag/header mutation, expiry,
65+
non-image isolation, tag-based purge through normal Fluxheim tooling, and
66+
fail-closed rejection of unknown or duplicate mutation IDs. Fluxheim does not
67+
embed VCL and the guest never receives raw cache objects.
68+
6269
`wasi-random-policy.wat` and `wasi-random-policy.toml` demonstrate the opt-in
6370
`1.7.8` WASI Preview 1 boundary. The module imports only `random_get`, and the
6471
config grants only randomness. Clocks require their own explicit grant.

packaging/rpm/fluxheim.spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ fi
159159
- Add the F5 iRules-style route access example and real listener smoke.
160160
- Add the nginx Lua/OpenResty-style bounded header-policy example.
161161
- Add the HAProxy Lua/SPOE-style bounded route and load-balancer example.
162+
- Complete the VCL-like cache-policy example and live operational smoke.
162163
- Harden snapshot opens against pathname races and isolate corruption fixtures
163164
behind safe store primitives.
164165

release-notes/RELEASE_NOTES_1.7.9.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ products.
2323
fixture. Live coverage proves symbolic canary/mirror selection, unavailable
2424
branch rejection, selected-route policy enforcement, native load balancing,
2525
and managed-cookie persistence without exposing backend addresses.
26+
- Promote the existing cache lookup/store WAT pair to the validated VCL-like
27+
parity example. The live smoke now proves pass, MISS/HIT, bounded variants,
28+
image-only TTL/tag/header metadata, expiry, tag purge, non-image isolation,
29+
and fail-closed invalid mutations.
2630

2731
## Security
2832

scripts/smoke_wasm_policy_examples.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ cargo test --locked -p fluxheim-server --features wasm \
1212
cargo test --locked -p fluxheim-server \
1313
--features "wasm,load-balancer,traffic-mirror" \
1414
native_wasm_route_decision
15+
cargo test --locked -p fluxheim-server --features wasm native_wasm_cache_
1516

1617
echo "wasm policy examples smoke: ok"

scripts/validate-wasm-example-plan.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ for file in \
1818
examples/wasm/openresty-header-policy.toml \
1919
examples/wasm/haproxy-spoe-routing-policy.wat \
2020
examples/wasm/haproxy-spoe-routing-policy.toml \
21+
examples/wasm/cache-lookup-policy.wat \
22+
examples/wasm/cache-store-policy.wat \
23+
examples/wasm/cache-policy.toml \
2124
scripts/smoke_wasm_policy_examples.sh
2225
do
2326
if [ ! -f "$file" ]; then

0 commit comments

Comments
 (0)