Skip to content

Commit 1a88e2f

Browse files
committed
Merge remote-tracking branch 'origin/main' into server-side-ad-templates-impl
2 parents d2f538b + a730bb1 commit 1a88e2f

64 files changed

Lines changed: 8802 additions & 3623 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/integration-tests.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,54 @@ jobs:
8383
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
8484
RUST_LOG: info
8585

86+
integration-tests-edgezero:
87+
name: integration tests (EdgeZero entry point)
88+
needs: prepare-artifacts
89+
runs-on: ubuntu-latest
90+
timeout-minutes: 15
91+
steps:
92+
- uses: actions/checkout@v4
93+
94+
- name: Set up integration test runtime
95+
id: shared-setup
96+
uses: ./.github/actions/setup-integration-test-env
97+
with:
98+
origin-port: ${{ env.ORIGIN_PORT }}
99+
check-dependency-versions: "false"
100+
install-viceroy: "true"
101+
build-wasm: "false"
102+
build-test-images: "false"
103+
104+
- name: Download integration test artifacts
105+
uses: actions/download-artifact@v4
106+
with:
107+
name: integration-test-artifacts
108+
path: ${{ env.ARTIFACTS_DIR }}
109+
110+
# Exercises the EdgeZero entry point against the same WASM binary by
111+
# pointing Viceroy at a config store with `edgezero_enabled = "true"`.
112+
# Scoped to the container-free EC lifecycle suite (minimal TCP origin), a
113+
# focused parity subset covering Fastly request conversion, config-store
114+
# dispatch, publisher fallback proxying, and end-to-end EC/API wiring on
115+
# the EdgeZero path. The legacy `integration-tests` job above still covers
116+
# the full framework matrix.
117+
- name: Run EdgeZero EC lifecycle tests
118+
run: >-
119+
cargo test
120+
--manifest-path crates/integration-tests/Cargo.toml
121+
--target x86_64-unknown-linux-gnu
122+
test_ec_lifecycle_fastly
123+
-- --include-ignored --test-threads=1
124+
env:
125+
WASM_BINARY_PATH: ${{ env.WASM_ARTIFACT_PATH }}
126+
INTEGRATION_ORIGIN_PORT: ${{ env.ORIGIN_PORT }}
127+
VICEROY_CONFIG_PATH: ${{ github.workspace }}/crates/integration-tests/fixtures/configs/viceroy-template-edgezero.toml
128+
# Opt into the EdgeZero entry-point canary in test_ec_lifecycle_fastly.
129+
# Only set here, so the legacy integration-tests job runs the same
130+
# scenarios through legacy_main without asserting the EdgeZero-only 405.
131+
EXPECT_EDGEZERO_ENTRY_POINT: "true"
132+
RUST_LOG: info
133+
86134
browser-tests:
87135
name: browser integration tests
88136
needs: prepare-artifacts

Cargo.lock

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ config = "0.15.19"
5656
cookie = "0.18.1"
5757
derive_more = { version = "2.0", features = ["display", "error"] }
5858
ed25519-dalek = { version = "2.2", features = ["rand_core"] }
59-
edgezero-adapter-axum = { git = "https://github.com/stackpop/edgezero", rev = "170b74b", default-features = false }
60-
edgezero-adapter-cloudflare = { git = "https://github.com/stackpop/edgezero", rev = "170b74b", default-features = false }
61-
edgezero-adapter-fastly = { git = "https://github.com/stackpop/edgezero", rev = "170b74b", default-features = false }
62-
edgezero-core = { git = "https://github.com/stackpop/edgezero", rev = "170b74b", default-features = false }
59+
edgezero-adapter-axum = { git = "https://github.com/stackpop/edgezero", rev = "38198f9839b70aef03ab971ae5876982773fc2a1", default-features = false }
60+
edgezero-adapter-cloudflare = { git = "https://github.com/stackpop/edgezero", rev = "38198f9839b70aef03ab971ae5876982773fc2a1", default-features = false }
61+
edgezero-adapter-fastly = { git = "https://github.com/stackpop/edgezero", rev = "38198f9839b70aef03ab971ae5876982773fc2a1", default-features = false }
62+
edgezero-core = { git = "https://github.com/stackpop/edgezero", rev = "38198f9839b70aef03ab971ae5876982773fc2a1", default-features = false }
6363
error-stack = "0.6"
6464
fastly = "0.11.12"
6565
fern = "0.7.1"
@@ -84,7 +84,7 @@ sha2 = "0.10.9"
8484
subtle = "2.6"
8585
temp-env = "0.3.6"
8686
tokio = { version = "1.49", features = ["sync", "macros", "io-util", "rt", "time"] }
87-
toml = "1.0"
87+
toml = "1.1"
8888
trusted-server-core = { path = "crates/trusted-server-core" }
8989
url = "2.5.8"
9090
urlencoding = "2.1"

crates/integration-tests/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Viceroy local server configuration template for integration tests —
2+
# EdgeZero entry-point variant.
3+
#
4+
# Identical to `viceroy-template.toml` but adds the `trusted_server_config`
5+
# config store with `edgezero_enabled = "true"`, so the same WASM binary routes
6+
# requests through the EdgeZero entry point instead of the legacy path. Used by
7+
# the `integration-tests-edgezero` CI job (via `VICEROY_CONFIG_PATH`) to exercise
8+
# Fastly request conversion, config-store dispatch, and end-to-end EC wiring on
9+
# the EdgeZero path. Keep the shared stores in sync with `viceroy-template.toml`.
10+
#
11+
# This configures the Viceroy runtime itself (backends, KV stores, etc.),
12+
# separate from the application config (trusted-server.toml).
13+
14+
[local_server]
15+
16+
[local_server.backends]
17+
18+
[local_server.kv_stores]
19+
# These inline placeholders satisfy Viceroy's local KV configuration
20+
# requirements without exercising KV-backed application behavior.
21+
[[local_server.kv_stores.counter_store]]
22+
key = "placeholder"
23+
data = "placeholder"
24+
25+
[[local_server.kv_stores.opid_store]]
26+
key = "placeholder"
27+
data = "placeholder"
28+
29+
[[local_server.kv_stores.creative_store]]
30+
key = "placeholder"
31+
data = "placeholder"
32+
33+
[[local_server.kv_stores.ec_identity_store]]
34+
key = "placeholder"
35+
data = "placeholder"
36+
37+
# Pre-seeded EC rows for KV-backed EC lifecycle tests. Each scenario
38+
# uses a separate row so withdrawal tombstones do not leak across
39+
# sequential scenario execution in the same Viceroy instance.
40+
[[local_server.kv_stores.ec_identity_store]]
41+
key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test01"
42+
data = '{"v":1,"created":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US","region":"CA"}}'
43+
44+
[[local_server.kv_stores.ec_identity_store]]
45+
key = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.test02"
46+
data = '{"v":1,"created":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US","region":"CA"}}'
47+
48+
[[local_server.kv_stores.ec_identity_store]]
49+
key = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.test03"
50+
data = '{"v":1,"created":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US","region":"CA"}}'
51+
52+
[[local_server.kv_stores.ec_identity_store]]
53+
key = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.test04"
54+
data = '{"v":1,"created":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US","region":"CA"}}'
55+
56+
[[local_server.kv_stores.ec_identity_store]]
57+
key = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.test05"
58+
data = '{"v":1,"created":1700000000,"consent":{"ok":true,"updated":1700000000},"geo":{"country":"US","region":"CA"}}'
59+
60+
[[local_server.kv_stores.ec_partner_store]]
61+
key = "placeholder"
62+
data = "placeholder"
63+
64+
# These are generated test-only key pairs, not production credentials.
65+
# The Ed25519 private key (data) and its matching public key (x in jwks_store below)
66+
# exist solely for signing and verifying tokens in the integration test environment.
67+
# They were generated specifically for testing and are safe to commit — they
68+
# have never been used in any production or staging environment.
69+
[local_server.secret_stores]
70+
[[local_server.secret_stores.signing_keys]]
71+
key = "ts-2025-10-A"
72+
data = "NVnTYrw5xoyTJDOwoUWoPJO3A6UCCXOJJUzgGTxxx7k="
73+
74+
[[local_server.secret_stores.api-keys]]
75+
key = "api_key"
76+
data = "test-api-key"
77+
78+
[local_server.config_stores]
79+
# Routes requests through the EdgeZero entry point. `is_edgezero_enabled`
80+
# in the Fastly adapter reads this key at runtime; `"true"` (or `"1"`)
81+
# enables EdgeZero, anything else falls back to the legacy path.
82+
[local_server.config_stores.trusted_server_config]
83+
format = "inline-toml"
84+
[local_server.config_stores.trusted_server_config.contents]
85+
edgezero_enabled = "true"
86+
87+
[local_server.config_stores.jwks_store]
88+
format = "inline-toml"
89+
[local_server.config_stores.jwks_store.contents]
90+
ts-2025-10-A = "{\"kty\":\"OKP\",\"crv\":\"Ed25519\",\"kid\":\"ts-2025-10-A\",\"use\":\"sig\",\"x\":\"UVTi04QLrIuB7jXpVfHjUTVN5aIdcbPNr50umTtN8pw\"}"
91+
ts-2025-10-B = "{\"kty\":\"OKP\",\"crv\":\"Ed25519\",\"kid\":\"ts-2025-10-B\",\"use\":\"sig\",\"x\":\"HVTi04QLrIuB7jXpVfHjUTVN5aIdcbPNr50umTtN8pw\"}"
92+
current-kid = "ts-2025-10-A"
93+
active-kids = "ts-2025-10-A,ts-2025-10-B"

crates/integration-tests/tests/common/ec.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,31 @@ fn mappings_to_json(mappings: &[BatchMapping]) -> Vec<Value> {
270270
// ---------------------------------------------------------------------------
271271

272272
/// Asserts the response has a specific HTTP status code.
273+
/// Asserts the running Viceroy instance is serving the EdgeZero entry point.
274+
///
275+
/// `main()` silently falls back to the legacy entry point when the config store
276+
/// cannot be opened or read, and the EC lifecycle scenarios pass on either path.
277+
/// This canary distinguishes them: the EdgeZero router returns a router-level
278+
/// `405` for methods outside its registered set (e.g. `TRACE`), whereas the
279+
/// legacy path proxied every method through to the publisher origin. Without it,
280+
/// a fixture/env/config-store regression could green the EdgeZero CI job while
281+
/// it actually exercises legacy.
282+
pub fn assert_edgezero_entry_point(base_url: &str) -> TestResult<()> {
283+
let client = Client::builder()
284+
.redirect(reqwest::redirect::Policy::none())
285+
.build()
286+
.expect("should build EdgeZero canary client");
287+
let response = client
288+
.request(reqwest::Method::TRACE, format!("{base_url}/"))
289+
.send()
290+
.change_context(TestError::HttpRequest)
291+
.attach("TRACE / (EdgeZero entry-point canary)")?;
292+
assert_status(&response, 405).attach(
293+
"EdgeZero canary: TRACE should return a router-level 405; a non-405 status \
294+
means main() fell back to the legacy entry point",
295+
)
296+
}
297+
273298
pub fn assert_status(resp: &Response, expected: u16) -> TestResult<()> {
274299
let actual = resp.status().as_u16();
275300
if actual != expected {

crates/integration-tests/tests/environments/fastly.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,19 @@ impl FastlyViceroy {
6767
///
6868
/// This contains `[local_server]` configuration (backends, KV stores,
6969
/// secret stores) that Viceroy needs, separate from the application config.
70+
///
71+
/// Honors the `VICEROY_CONFIG_PATH` environment variable so a CI job can
72+
/// point the same WASM binary at an alternative config store — e.g. the
73+
/// EdgeZero fixture that sets `trusted_server_config.edgezero_enabled =
74+
/// "true"` to exercise the EdgeZero entry point. Mirrors the browser
75+
/// harness's `global-setup.ts`, which reads the same variable. Falls back to
76+
/// the default legacy template when unset.
7077
fn viceroy_config_path(&self) -> std::path::PathBuf {
78+
if let Ok(path) = std::env::var("VICEROY_CONFIG_PATH") {
79+
if !path.is_empty() {
80+
return std::path::PathBuf::from(path);
81+
}
82+
}
7183
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
7284
.join("fixtures/configs/viceroy-template.toml")
7385
}

crates/integration-tests/tests/integration.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ fn test_ec_lifecycle_fastly() {
166166

167167
log::info!("EC lifecycle tests: Viceroy running at {}", process.base_url);
168168

169+
// EdgeZero entry-point canary. This same test runs in two CI jobs: the
170+
// legacy `integration-tests` job (default Viceroy config, legacy_main) and
171+
// the `integration-tests-edgezero` job (EdgeZero config store, edgezero_main).
172+
// Only assert the canary when the job opted into the EdgeZero path via
173+
// EXPECT_EDGEZERO_ENTRY_POINT; on the legacy path TRACE is proxied (not 405ed)
174+
// and the scenarios still validate legacy behavior. The canary guards against
175+
// the EdgeZero job silently greening on legacy if the config store cannot be
176+
// read (main() falls back to legacy_main).
177+
if std::env::var("EXPECT_EDGEZERO_ENTRY_POINT").as_deref() == Ok("true") {
178+
common::ec::assert_edgezero_entry_point(&process.base_url)
179+
.expect("EdgeZero entry-point canary failed: TRACE did not return a router-level 405");
180+
}
181+
169182
for scenario in EcScenario::all() {
170183
log::info!(" Running EC scenario: {scenario:?}");
171184
scenario

crates/trusted-server-adapter-fastly/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ serde = { workspace = true }
2323
serde_json = { workspace = true }
2424
toml = { workspace = true }
2525
trusted-server-core = { workspace = true }
26+
url = { workspace = true }
2627
urlencoding = { workspace = true }
2728

2829
[dev-dependencies]
30+
bytes = { workspace = true }
2931
edgezero-core = { workspace = true, features = ["test-utils"] }
32+
trusted-server-core = { workspace = true, features = ["test-utils"] }

0 commit comments

Comments
 (0)