Skip to content

Adopt edgezero strict-clippy gate and PR #257 API#108

Merged
aram356 merged 24 commits into
mainfrom
chore/edgezero-strict-clippy
Jun 12, 2026
Merged

Adopt edgezero strict-clippy gate and PR #257 API#108
aram356 merged 24 commits into
mainfrom
chore/edgezero-strict-clippy

Conversation

@aram356

@aram356 aram356 commented May 18, 2026

Copy link
Copy Markdown
Contributor

Closes #107.

Tracks stackpop/edgezero#257 (chore/strict-clippy) and pulls mocktioneer onto the same strict clippy gate plus the defensive-coding pass it ships.

Summary

  • All edgezero-* workspace deps point at branch = "chore/strict-clippy" pending PR #257 merge.
  • Root Cargo.toml adopts [workspace.lints.clippy] from edgezero: pedantic = warn, restriction = deny, 13-entry allow-list. [workspace.lints.rust] denies unsafe_code.
  • New clippy.toml mirrors edgezero's test exemptions.
  • [lints] workspace = true added to all four crate Cargo.tomls.
  • Migrated to the new edgezero API: Router::oneshot returns Result, Body is Once/Stream with Option-returning bytes, run_app moved to dev_server::run_app, IntoResponse::into_response() fallible.
  • All eleven route handlers now return Result<Response, EdgeError> for a uniform fallibility contract.

Refactor approach

~700 clippy findings resolved through real refactors per the upstream principle:

  • struct fields, enum variants, impl methods reordered alphabetically (~300 sites);
  • numeric literals typed (11_i32, 2.52.5_f64);
  • single-char idents renamed where they don't carry spec meaning;
  • #[inline] added to public fns/methods;
  • test_ prefix dropped from test fn names;
  • as casts replaced with f64::from(i32::try_from(...)) / saturating arithmetic;
  • integration tests wrapped in #[cfg(test)] mod tests to satisfy tests_outside_test_module;
  • OpenRTB w/h fields renamed to width/height with #[serde(rename = "w"/"h")] to preserve JSON wire format;
  • Site._refr#ref (raw identifier, default-serialises to ref);
  • Geo._typekind with #[serde(rename = "_type")].

Remaining exceptions

Five call-site #[expect(..., reason = "...")] annotations remain, each documenting a genuine constraint:

Site Lint Constraint
auction.rs::get_cpm float_arithmetic CPM is f64 by API
render.rs::svg_layout 7-lint layout-math cluster i64 banner-dimension math on the SVG layout path
adapter-axum/main.rs print_stderr startup-error path before logger init
adapter-cloudflare/main.rs print_stderr host-side stub reminding operator to target wasm32
adapter-fastly/main.rs print_stderr (+ a documented dead_code cfg_attr) same wasm32 stub pattern

Test plan

  • cargo check --workspace --all-targets
  • cargo check --workspace --all-targets --features "fastly cloudflare"
  • cargo clippy --workspace --all-targets --all-features -- -D warnings (0 findings)
  • cargo test --workspace --all-targets (90 tests pass)
  • cargo fmt --all -- --check

Follow-up

When stackpop/edgezero#257 merges to main, flip the branch = "chore/strict-clippy" entries in the root Cargo.toml back to branch = "main" and rerun cargo update.

aram356 added 7 commits May 18, 2026 15:04
Track stackpop/edgezero#257 (`chore/strict-clippy` branch) and mirror the
same strict clippy gate workspace-wide: `pedantic = warn`,
`restriction = deny`, with a 13-entry workspace allow-list. Adopt the
test exemption set in `clippy.toml`.

The PR includes a defensive-coding pass that changes upstream APIs:
`Router::oneshot` now returns `Result<Response, EdgeError>`, `Body` is a
`Once`/`Stream` enum whose bytes are `Option`-returning, `run_app` moved
to `dev_server::run_app`, and `IntoResponse::into_response()` is now
fallible. Adapter wiring and test helpers are updated accordingly.

Clippy fallout (~700 findings) is resolved through real refactors per
the upstream principle "every removed allow corresponds to a real
refactor, not a sprinkling of `#[allow]`/`#[expect]`": fields and items
reordered alphabetically, numeric literals typed, single-char idents
renamed, public fns inlined, test fns drop the `test_` prefix, casts
replaced with checked conversions, integration tests wrapped in
`#[cfg(test)] mod tests`. OpenRTB `w`/`h` fields are renamed to
`width`/`height` with `#[serde(rename)]` to preserve the JSON wire
format; `_ref` becomes `r#ref`; `_type` becomes `kind` with a serde
rename.

All route handlers now uniformly return `Result<Response, EdgeError>`.

Five call-site `#[expect]` annotations remain, each documented with
`reason = "..."`: float arithmetic in CPM fallback, the SVG layout math
cluster on i64 banner dimensions, and three `print_stderr` sites in
adapter startup-error paths where no logger is initialised.
The Rust-side renames `w`/`h` → `width`/`height`, `_ref` → `r#ref`, and
`_type` → `kind` rely on `#[serde(rename = ...)]` (or raw-identifier
default mapping for `r#ref`) to preserve the JSON contract. None of the
existing tests assert the JSON key names, so a broken rename would
silently change the wire format. Add seven focused round-trip tests
that pin the serialized key names and verify deserialization from
spec-shaped JSON.
Track the latest commits on stackpop/edgezero `chore/strict-clippy`
(a26704f7 → 97d02de5), which include the upstream toolchain bump to
Rust 1.95.0 alongside `ctor 0.10 → 1.0`, `viceroy 0.17`, and
no-features-only clippy fixes.

Pin `.tool-versions` to `rust 1.95.0` and update the CLAUDE.md
toolchain table to match.

Rust 1.95.0 ships two new restriction-clippy lints we previously
weren't subject to:

- `doc_paragraphs_missing_punctuation` — 59 sites across aps, mediation,
  render, and auction modules where doc-comment paragraphs lacked a
  terminating `.`. Fixed by appending punctuation at each site.
- `duration_suboptimal_units` — `Duration::from_secs(10 * 60)` for the
  JWKS cache TTL becomes `Duration::from_mins(10)`.

All gates green: cargo check / clippy (workspace, all-targets,
all-features, `-D warnings`) / fmt / test (90 tests).
Mocktioneer's CI previously ran `cargo test` and `cargo check
--features "fastly cloudflare"` only on the host triple. The Fastly
and Cloudflare adapters' real entry points compile only under their
wasm targets, so a worker/fastly version skew or a `run_app` signature
change upstream would not surface in CI — it would surface at deploy
time.

Add an `adapter-wasm-check` matrix mirroring stackpop/edgezero#257's
`adapter-wasm-tests` matrix (compile-check only, since mocktioneer's
adapter crates do not yet carry a wasm-runtime contract suite):

  - cloudflare → `cargo check ... --target wasm32-unknown-unknown`
  - fastly     → `cargo check ... --target wasm32-wasip1`

This immediately surfaced the bumps required to track the latest
edgezero head:

  - workspace `worker` 0.7 → 0.8 and `fastly` 0.11.9 → 0.12 (edgezero's
    PR #257 already moved to these majors; the host build hid the
    skew because the host stubs don't touch those types);
  - `edgezero_adapter_cloudflare::run_app` gained a leading manifest
    `&str` parameter (matching the existing Fastly signature). Updated
    the cloudflare adapter `#[event(fetch)]` entry point accordingly.

Dropped the now-redundant host-step `Add wasm32-wasi target` and
`Setup Viceroy` from the main `test` job — they were never exercised
there and the matrix job installs them per-cell as needed.
Replace the wasm compile-check matrix with a wasm test matrix that
actually executes the adapter dispatch path inside the wasm runtime.

Contract tests:
  - `crates/mocktioneer-adapter-fastly/tests/contract.rs` — exercises
    `dispatch(&app, FastlyRequest)` for `GET /` and `GET /pixel?pid=...`
    against `wasm32-wasip1` via Viceroy.
  - `crates/mocktioneer-adapter-cloudflare/tests/contract.rs` — same two
    routes via the cloudflare `dispatch(app, req, env, ctx)` path under
    `wasm32-unknown-unknown` via `wasm-bindgen-test`.

Both files annotate `#![expect(deprecated, reason = "...")]` because
the low-level `dispatch` entry points are the test surface that
remains public — the higher-level `dispatch_with_config*` variants
require irrelevant config-store wiring for our simple contracts.

CI matrix mirrors stackpop/edgezero#257:
  - cloudflare cell installs `wasm-bindgen-cli` at the version pinned
    in `Cargo.lock` and sets `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER`.
  - fastly cell installs Viceroy at the version pinned in
    `.tool-versions` (now `viceroy 0.17.0`, matching upstream) and sets
    `CARGO_TARGET_WASM32_WASIP1_RUNNER`.

`.cargo/config.toml` keeps a workspace-level `[target.wasm32-wasip1]
runner = "viceroy run -C crates/.../fastly.toml --"` so the same
`cargo test` invocation works locally with the project's fastly.toml.
The env var set in CI takes precedence and uses bare defaults.

`wasm-bindgen-test = "0.3"` added as a wasm32-target dev-dependency to
the cloudflare adapter crate.
The six Node-20-runner actions emit deprecation warnings on every
workflow run; GitHub will remove the runners in a future schedule.
Bump each to its current major (Node 24), matching the alignment done
upstream in stackpop/edgezero#257:

  - actions/checkout              v4 → v6  (test, codeql, format,
                                            deploy-docs, docker)
  - actions/cache                 v4 → v5  (test, format)
  - actions/setup-node            v4 → v6  (test, deploy-docs, format)
  - actions/configure-pages       v4 → v6  (deploy-docs)
  - actions/deploy-pages          v4 → v5  (deploy-docs)
  - actions/upload-pages-artifact v3 → v5  (deploy-docs)

actions/upload-artifact@v4, actions-rust-lang/setup-rust-toolchain@v1,
docker/*, and github/codeql-action@v4 are already at their current
majors and left untouched.

@prk-Jr prk-Jr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review

Summary

Thoroughly executed strict-clippy adoption. ~700 findings resolved through real refactors (not #[allow] suppression), new edgezero API migration is complete, and the wire-format round-trip tests are exactly the right safety net for a rename-heavy change. All CI gates pass locally. No blocking issues — two questions about field naming intent and one pre-existing WASM compatibility concern worth tracking separately.

Findings

❓ Questions

  • Geo.kind wire key vs. OpenRTB spec — the kind field now maps to "_type" (not the spec's "type"), while type2 carries the spec-conformant key. This looks intentional and the round-trip test confirms it, but doc comments distinguishing the two fields would prevent future confusion. (openrtb.rs:405)
  • Site.ref_ — what spec field does this represent?ref_ serialises to "ref_" literally with no serde rename; no OpenRTB 2.5/3.0 spec field maps to that key. Worth a doc comment noting whether this is a compat shim or extension. (openrtb.rs:275)

🤔 Thoughts

  • Empty impl SizeDimensions {} — dead impl block, likely leftover from the reorder pass. (routes.rs:127)
  • PixelQueryParams { .. } discards pid silently — correct for a mock, but a comment explaining the intentional discard prevents future "is this a bug?" reads. (routes.rs:347)
  • run_in_browser but Node is the actual runnerwasm_bindgen_test_configure!(run_in_browser) is misleading; a comment noting the env-var fallback to Node would help. (contract.rs:13)
  • WASM compatibility: std::sync::Mutex + std::time::Instant in verification.rsLazyLock<Mutex<…>> and Instant are not available on wasm32-unknown-unknown. This pre-dates the PR and the new WASM contract tests don't exercise the verify path, so it's hidden. Not a regression here, but the new WASM CI matrix makes it the right moment to track this in a follow-up issue. (verification.rs:10-16)

📝 Notes

  • wasm-bindgen-test = "0.3" uses a semver range — safe because Cargo.lock is committed, but inconsistent with the explicit CLI version-pin in CI. Consider = "0.3.71" to match. (mocktioneer-adapter-cloudflare/Cargo.toml:31)

👍 Praise

  • Wire-format round-trip tests — the seven serde tests in openrtb.rs (lines 582–703) are the right safety net for this rename-heavy PR. They pin JSON key names independently of struct field names, so a future accidental serde annotation removal becomes a test failure, not a silent wire-format change.
  • #[expect(..., reason = "...")] usage — all five exception sites are correctly documented with accurate constraint descriptions, and each suppresses individual lints rather than using a blanket restriction. This is exactly how these annotations should be used.
  • WASM contract test matrix — moving from a compile-check matrix to an actual execution matrix (Fastly via Viceroy, Cloudflare via wasm-bindgen-test-runner) is a meaningful CI improvement. This will surface adapter-dispatch regressions that host-only cargo test cannot catch.
  • Alphabetical field ordering — applied systematically and completely across all changed files. Predictable field lookup without requiring a secondary index.

CI Status

  • fmt: PASS
  • clippy: PASS
  • tests: PASS (90 tests)

Comment thread crates/mocktioneer-core/src/openrtb.rs Outdated
Comment thread crates/mocktioneer-core/src/openrtb.rs Outdated
Comment thread crates/mocktioneer-core/src/routes.rs Outdated
Comment thread crates/mocktioneer-core/src/routes.rs
Comment thread crates/mocktioneer-adapter-cloudflare/tests/contract.rs
Comment thread crates/mocktioneer-adapter-cloudflare/Cargo.toml Outdated
aram356 added 3 commits May 20, 2026 20:14
Completes the toolchain bump for the container build: the `RUST_VERSION`
build arg now matches `.tool-versions` (1.95.0). Switch the runtime
stage from the pinned `debian:bookworm-slim` to `debian:stable-slim` so
the image tracks the current Debian stable.
Routine `cargo update` of registry dependencies — `anyhow`,
`async-compression`, `syn`, and other transitive crates move to their
latest semver-compatible releases. No manifest changes; reproducible
build inputs only.
Integrates PR #80 (Trusted Server v1.1 signature verification) and the
fixed-price auction rework into the edgezero strict-clippy branch.

Conflict resolutions:
- auction.rs: took main's pricing model (FIXED_BID_CPM, STANDARD_SIZES
  array, largest-area APS selection, ignored bid override); re-applied
  this branch's OpenRTB width/height field names and strict-clippy
  compliance. SIZE_MAP/get_cpm/phf are gone.
- verification.rs: took main's Trusted Server v1.1 verification;
  re-applied the edgezero #257 Body/HTTP API shape and strict-clippy
  style (inline, ident renames, doc punctuation, from_mins).
- routes.rs: handle_sizes keeps the Result<Response, EdgeError> return
  type; drops the cpm field and the get_cpm import (no longer exists).
- render.rs / aps_endpoints.rs: kept this branch's #[cfg(test)] mod
  wrapping and test renames; folded in main's new tests and the
  largest-area rename.
- Cargo.toml: phf dropped, js-sys added (both from main).

All gates green: clippy (workspace, all-targets, all-features,
-D warnings), 119 tests, fmt, "fastly cloudflare" feature check, and
both wasm-target builds.
Review by @prk-Jr — no blocking issues; resolves the actionable items:

- openrtb.rs: document the `Geo.kind`/`Geo.type2` and `Site.r#ref`/
  `Site.ref_` field pairs — which carries the OpenRTB spec key and
  which is a non-spec legacy-compat field.
- routes.rs: remove the empty `impl SizeDimensions {}` block left over
  from the item-reorder pass.
- routes.rs: comment `handle_pixel`'s `PixelQueryParams { .. }` discard
  — `pid` is validated on extraction but intentionally unused.
- adapter-cloudflare contract.rs: comment that `run_in_browser` only
  declares the harness mode; CI runs headless under Node via the
  `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER` runner.
- adapter-cloudflare Cargo.toml: pin `wasm-bindgen-test` to `=0.3.71`
  to match the explicit CLI version-pin in CI.

The reviewer's WASM-compatibility concern (`std::time::Instant` in the
JWKS cache panics on wasm32-unknown-unknown) is pre-existing and tracked
separately in #109.
@aram356

aram356 commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review @prk-Jr. Addressed in 5ae2cd5:

Finding Resolution
Geo.kind wire key vs spec Doc comments added to kind (non-spec _type compat) and type2 (spec Geo.type).
Site.ref_ spec field Doc comments added to r#ref (spec Site.ref) and ref_ (non-spec legacy-compat field).
Empty impl SizeDimensions {} Removed — leftover from the reorder pass.
PixelQueryParams { .. } discards pid Comment added: pid is validated on extraction, intentionally unused.
run_in_browser misleading Comment added explaining the runner (CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER) selects the headless-Node environment.
wasm-bindgen-test = "0.3" range Pinned to =0.3.71 to match the CI CLI version-pin.
WASM Instant/Mutex in verification.rs Pre-existing; tracked as a follow-up in #109 (Instant::now() panics on wasm32-unknown-unknown).

All gates still green: clippy (-D warnings), 119 tests, fmt.

@aram356 aram356 requested a review from prk-Jr May 21, 2026 05:39

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Review of PR #108 found one blocking e2e test-registration issue plus two non-blocking comments. Rust/docs gates passed locally; Playwright passed but only registered 2 tests, which is the coverage issue below.

Folded into body

🔧 Playwright only registers 2 tests because AD_SIZES is populated too late — tests/playwright/creative-visibility.test.ts:40

AD_SIZES starts as [] and is populated in test.beforeAll, but Playwright registers tests synchronously while loading this module. The loop at line 40, and the second loop at line 103, therefore runs over an empty array, so the per-size tests are never registered. Local npm test only reported 2 tests instead of the intended per-size suite.

Suggestion: Use a static supported-size list for test registration and assert /_/sizes matches it, or move the dynamic iteration inside an async test with test.step after fetching sizes:

test('all supported SVG creatives render visibly', async ({ request, page }) => {
  const response = await request.get('/_/sizes')
  const data = (await response.json()) as { sizes: AdSize[] }

  for (const size of data.sizes) {
    await test.step(`${size.width}x${size.height}`, async () => {
      await page.goto(`/static/img/${size.width}x${size.height}.svg`)
      // existing assertions...
    })
  }
})

📝 OpenRTB response example omits the signature-status query parameter — docs/api/openrtb-auction.md:107

iframe.html.hbs appends {{#if SIG}}&sig={{SIG}}{{/if}}, and iframe_html always sets SIG from metadata.signature.url_param(). For a minimal unsigned request, the creative URL includes &sig=not_present.

Suggestion: If this response example is intended to be exact, include &sig=not_present in the adm URL or add an ellipsis/note that the markup is abbreviated.

Comment thread crates/mocktioneer-adapter-cloudflare/tests/contract.rs Outdated
aram356 added 3 commits May 26, 2026 00:55
Mocktioneer was missing a Spin adapter. Add `mocktioneer-adapter-spin`
modelled after the cloudflare/fastly crates and edgezero's
app-demo-adapter-spin example:

  crates/mocktioneer-adapter-spin/
    Cargo.toml           bin (host stub) + cdylib (wasm32-wasip1)
    spin.toml            Spin v2 manifest
    src/main.rs          host stub — reminds operators to `spin up`
    src/lib.rs           `#[http_component]` handler that delegates to
                         `edgezero_adapter_spin::run_app::<MocktioneerApp>`
    tests/contract.rs    wasm32-wasip1 contract tests run via wasmtime

Workspace + manifest wiring:
- Add to `[workspace.members]`.
- Add `spin-sdk = "5.2"` and `edgezero-adapter-spin` workspace deps
  (5.2 matches edgezero's PR #257 pin — upgrade to 6.0 is upstream-
  blocked by `Method` variant API breaks; tracked separately).
- Register `[adapters.spin.*]` in `edgezero.toml` and append `"spin"`
  to every trigger's adapter list.

CI matrix:
- Add `spin` cell to `adapter-wasm-tests` (wasm32-wasip1 / wasmtime).
- Install wasmtime via the official script when matrix.adapter == spin.
- Reuses the same `runner_env` mechanism as fastly; matrix sets
  `CARGO_TARGET_WASM32_WASIP1_RUNNER=wasmtime run`, overriding the
  workspace `.cargo/config.toml` viceroy default for this cell.

One documented `#![cfg_attr(... expect(unsafe_code, reason = "..."))]`
at the wasm32 cfg: `#[http_component]` expands to WASI wit-bindgen
code containing `#[export_name]`, an `unsafe fn` declaration, and an
unsafe block, all of which trip `unsafe_code = "deny"`. This is the
only entry into the Spin runtime, so the macro expansion is
intrinsically unsafe.

All gates green: clippy / 121 tests (host) / fmt /
`"fastly cloudflare spin"` feature check / wasm builds for all three
adapter targets. Spin contract test (`root_dispatches_through_spin_runtime`,
`pixel_returns_gif_through_spin_runtime`) verified locally via wasmtime.
@ChristianPavilonis observed the CI logs for this PR show the cloudflare
contract tests running headless in Firefox, not Node. My previous comment
on this line (added in 5ae2cd5) incorrectly claimed Node. `run_in_browser`
genuinely selects the wasm-bindgen browser harness; the ubuntu-latest CI
image ships with geckodriver, so the harness lights up Firefox.

Update the comment to accurately describe what actually runs.
@aram356

aram356 commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ChristianPavilonis — you're right, my earlier comment on this line was wrong. The tests really do execute in the browser harness (headless Firefox via the geckodriver on the ubuntu-latest runner image), not Node.

Fixed in 1098e83 — comment now accurately describes the browser harness and where the runner wiring lives (CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner).

Kept run_in_browser because the tests construct worker::Env/worker::Context via js_sys::Object, and the browser engine matches the Cloudflare Workers runtime more closely than a pure Node fallback would.

@prk-Jr asked what spec field `Site.ref_` maps to. The honest answer
is: none — and `Geo.kind` (renamed earlier from `_type`) is the same
mistake.

`git blame` shows both fields were added in 5bb01d9 by the same author
in the same commit as their spec-conformant siblings. The pattern is
clear: the author wrote the conventional Rust keyword-escape form
first (`ref_`, `_type`), realized that serialised to `"ref_"`/`"_type"`
which don't match the OpenRTB 2.x spec, then added `_ref`/`type2` with
`#[serde(rename = "ref"/"type")]` to fix the wire format, and never
removed the original attempt. Neither field is read or written outside
the round-trip tests I added in this PR, and dropping them is
behavior-neutral (`#[serde(deny_unknown_fields)]` is not enabled, so
incoming `"ref_"`/`"_type"` keys are silently ignored either way).

My previous attempt to address the review (5ae2cd5) added speculative
"legacy compatibility" doc comments rather than answering the question.
This commit answers it by removing the dead fields and tightening the
round-trip tests to assert just the spec keys.
@aram356

aram356 commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

@prk-Jr — you're right that my earlier reply dodged your question. I added speculative "legacy compatibility" doc comments rather than actually answering what ref_ was for.

I dug into the history: git log -S "pub ref_:" turns up commit 5bb01d9 (Sep 2025), where ref_ and _ref (now r#ref) were added back-to-back in the same hunk by the same author. The pattern was: write ref_ first (conventional Rust keyword-escape — but that serialises to "ref_", which isn't an OpenRTB key), realise it's wrong, add _ref with #[serde(rename = "ref")] to fix the wire format, then forget to remove the first attempt. Geo._type/type2 (now Geo.kind/type2) is the exact same mistake in the same commit.

Neither field is read or written anywhere outside the round-trip tests I added in this PR — they are dead code.

Fixed in 053037c by removing both fields and tightening the round-trip tests to assert just the spec keys (Site.r#ref → "ref" and Geo.type2 → "type"). The change is behavior-neutral: #[serde(deny_unknown_fields)] isn't set, so any incoming "ref_"/"_type" keys were being silently ignored regardless.

All gates still green.

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review

Thanks for the strict-clippy/EdgeZero API migration work. The Rust gates and current PR checks are green, but I’m requesting changes because GitHub reports the branch does not merge cleanly with current main. Please update the branch, resolve conflicts, and rerun the full gate set before approval.

🔧 Needs change

  • PR is not mergeable against current main: GitHub reports mergeable: false / mergeable_state: dirty. A local merge-tree check against current origin/main also reports conflicts in .tool-versions, Cargo.lock, Cargo.toml, crates/mocktioneer-core/src/mediation.rs, crates/mocktioneer-core/src/render.rs, crates/mocktioneer-core/src/routes.rs, and crates/mocktioneer-core/tests/endpoints.rs. Please rebase or merge current main, preserve both the strict-clippy/Spin changes and the newer Edge Cookie/trusted-server integration, then rerun CI.

🏕 Documentation follow-ups

  • Update adapter/project docs for Spin: The PR adds crates/mocktioneer-adapter-spin and registers spin in edgezero.toml, but project docs/conventions still describe only Axum/Fastly/Cloudflare in several places (for example CLAUDE.md). Please update the adapter overview, getting-started/configuration docs, and project conventions to include Spin/Fermyon where adapters are enumerated.
  • Trusted Server docs/examples are stale: The current verifier requires the v1.1 fields (version, request_host, request_scheme, fresh ts), exact compact signing payload bytes, base64url-without-padding keys/signatures, DNS-valid site.domain, and request_host matching site.domain. The docs/examples should be updated or split so the default unsigned example does not always show failed signature verification.
  • OpenRTB response example omits sig: Runtime adm now always includes a signature-status query parameter (sig=verified, sig=failed, or sig=not_present). Please either include &sig=not_present in exact examples or mark the markup as abbreviated.

CI / validation observed

  • cargo fmt --all -- --check: PASS
  • cargo clippy --workspace --all-targets --all-features -- -D warnings: PASS
  • cargo test --workspace --all-targets: PASS
  • cargo check --workspace --all-targets --features "fastly cloudflare": PASS
  • GitHub PR checks: PASS at the reviewed head

Comment thread .github/workflows/test.yml
aram356 added 4 commits June 1, 2026 00:03
Two cosmetic differences against edgezero's `Run Format` workflow:
- Top-level `permissions:` moves above `concurrency:` (matching edgezero's order).
- Drop the `~/.cargo/bin/` cache path — this workflow only runs fmt and
  clippy, which install no cargo binaries, so caching that directory was
  dead weight.

format.yml now matches edgezero byte-for-byte. No matrix involved (the
adapter-wasm-tests matrix lives in test.yml).
Integrates PR #98 (Edge Cookie sync support for trusted-server) into
the strict-clippy / edgezero #257 branch.

Conflict resolutions:
- routes.rs: took main's new handlers (handle_sync_start, handle_sync_done,
  handle_resolve) + helpers (validate_ec_id, validate_ip_address,
  validate_ts_synced, authorize_pull_token, etc.) and applied this
  branch's strict-clippy compliance: all handlers return
  Result<Response, EdgeError>; new types (SyncStartParams, SyncDoneParams,
  ResolveParams, ResolveResponse) and PullAuthOutcome moved into the
  canonical struct/enum grouping before fns to satisfy
  arbitrary_source_item_ordering; absolute_paths fixed via `use std::env`;
  inlined format args, ident renames, .to_string() → .to_owned(),
  assertions_on_result_states (Result::unwrap on infallible cases).
- render.rs: took main's new EC types (EdgeCookieInfo struct,
  MOCKTIONEER_SOURCE_DOMAIN const, extract_ec_hash, extract_ec_info)
  with strict-clippy compliance — #[inline]/#[must_use], alphabetical
  fields, renamed single-char idents, terminal doc punctuation,
  backticked OpenRTB. Folded `edge_cookie: EdgeCookieInfo` into the
  existing CreativeMetadata struct.
- mediation.rs: merged the import — both `iframe_html` (ours) and
  `extract_ec_info` (theirs) are needed.
- tests/endpoints.rs: moved main's new sync-endpoint test fns inside
  this branch's `#[cfg(test)] mod tests` wrapper, dropped `test_`
  prefix, replaced inline block_on/oneshot with the existing
  `dispatch(&app, request)` helper. Took main's looped
  options_includes_allow_and_cors_headers over the new sync paths.
- openrtb.rs: reordered new Eid/EidUid struct fields alphabetically;
  backticked OpenRTB in doc comments.
- Cargo.toml: edgezero deps stay on chore/strict-clippy branch (incl.
  edgezero-adapter-spin); added main's new workspace deps (subtle,
  sha2); aligned fastly to 0.12.1 and worker to 0.8.3 (main's pin).
- Cargo.lock: took ours and reconciled via cargo.
- .tool-versions: kept viceroy 0.17.0 entry (this branch's pin).

All gates green: clippy (-D warnings), 161 tests (up from 119), fmt,
"fastly cloudflare spin" feature check.
- **Playwright `AD_SIZES` registration bug** (`tests/playwright/
  creative-visibility.test.ts:40` — @ChristianPavilonis): the loop was
  iterating a list populated in `beforeAll`, but Playwright registers
  tests synchronously at module load, so only 2 of the intended
  per-size suite were actually registered. Switch to a static
  `AD_SIZES` constant (mirrors `STANDARD_SIZES` in `auction.rs`) and
  add a `sizes endpoint matches static AD_SIZES list` assertion so any
  drift between the server list and the test list fails loudly.
  `npx playwright test --list` now reports 41 tests (was 2).

- **OpenRTB response example missing `sig` query parameter**
  (`docs/api/openrtb-auction.md:107` — @prk-Jr, @ChristianPavilonis):
  runtime `adm` always includes `&sig=verified|failed|not_present`
  (set by `iframe_html` from `metadata.signature.url_param()`). The
  exact-output example now matches: `…?crid=mocktioneer-imp-1&sig=not_present`.

- **Pin Wasmtime instead of `curl ... | bash` of the latest**
  (`.github/workflows/test.yml:139` — @ChristianPavilonis): add
  `wasmtime 45.0.0` to `.tool-versions` and pass `-v "v$VERSION"` to
  the installer so the spin matrix cell fetches a specific tagged
  release. Removes the unpinned/latest-installer supply-chain concern
  and matches how `viceroy`/`wasm-bindgen-cli` are pinned.

- **Add Spin to CLAUDE.md adapter/project docs** (@ChristianPavilonis):
  workspace layout, compilation-targets table, `edgezero-cli serve`
  examples, and the key-files-reference table all now mention the
  `mocktioneer-adapter-spin` crate alongside axum/cloudflare/fastly.

prk-Jr's earlier comments (`wasm-bindgen-test` pin, cloudflare contract
test comment, `_ref`/`_type` doc / removal) were already resolved in
prior commits on this branch.

All gates green: clippy `-D warnings`, 161 tests (host), fmt,
`"fastly cloudflare spin"` feature check; Playwright now lists 41
tests vs the previous 2.
@aram356

aram356 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ChristianPavilonis @prk-Jr. PR is now MERGEABLE and all open feedback addressed.

Merge of main (bf4ebc8) — PR #98 (Edge Cookie sync) is now folded in. Conflicts in routes.rs, render.rs, mediation.rs, tests/endpoints.rs, openrtb.rs, Cargo.toml, .tool-versions resolved by taking main's new behaviour (sync_start / sync_done / resolve handlers, EC types in CreativeMetadata, subtle/sha2 deps) and re-applying this branch's strict-clippy compliance + edgezero #257 API (Result<Response, EdgeError> handlers, alphabetical item ordering, width/height field names, etc.). New EC types are placed in the canonical struct/enum grouping before fns. Test count is now 161 (was 119; +42 from PR #98).

Open feedback resolved in 52c5459:

Item Resolution
🔧 Playwright AD_SIZES bug (@ChristianPavilonis) Switched to a static AD_SIZES constant (mirrors STANDARD_SIZES in auction.rs) + a drift-detection assertion. npx playwright test --list now reports 41 tests (was 2).
📝 OpenRTB response example missing sig (@prk-Jr, @ChristianPavilonis) Updated adm example URL to include &sig=not_present.
🤔 Pin Wasmtime instead of curl ... | bash of latest (@ChristianPavilonis) Added wasmtime 45.0.0 to .tool-versions; CI installs that version via bash -s -- -v "v$VERSION". Matches how viceroy and wasm-bindgen-cli are pinned.
🏕 Spin in CLAUDE.md (@ChristianPavilonis) Workspace layout, compilation-targets table, edgezero-cli serve examples, and key-files-reference table all now include mocktioneer-adapter-spin.
🏕 Trusted Server docs/examples stale (@ChristianPavilonis) Out of scope for this PR — those docs evolve with the verifier itself. Worth a follow-up issue if you want me to file one.

All gates still green: clippy -D warnings, 161 tests, fmt, "fastly cloudflare spin" feature check.

aram356 added 2 commits June 5, 2026 10:20
The wasmtime.dev installer rejects `-v` as an unknown option (it offers
`--release`/`--dev`/`--version` only). The spin matrix cell on the latest
PR run failed at the Setup Wasmtime step with:

    Error: unknown option: '-v'

Switch the short flag to the long `--version` form. Comment refreshed to
match.

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review

Approved. The required local gates and GitHub PR checks are passing. I left one non-blocking reproducibility note on the Wasmtime setup so the pinned .tool-versions version cannot be bypassed by a future runner image that happens to preinstall Wasmtime.

Comment thread .github/workflows/test.yml Outdated
prk-Jr
prk-Jr previously approved these changes Jun 10, 2026

@prk-Jr prk-Jr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@ChristianPavilonis flagged that the previous `if ! command -v wasmtime`
guard would silently bypass the `.tool-versions` pin if the GitHub
runner image later preinstalls Wasmtime — any version would satisfy the
guard and the install step would skip.

Drop the guard so the pinned version is always installed. The install
script is small/fast (single curl + tarball extract) and `~/.wasmtime/bin`
is prepended to PATH for the rest of the job, so this shadows any
system wasmtime.
@aram356 aram356 dismissed stale reviews from prk-Jr and ChristianPavilonis via 9c76c72 June 10, 2026 19:05
@aram356

aram356 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the heads-up @ChristianPavilonis. Addressed in 9c76c72 — dropped the command -v wasmtime guard so the pinned ${{ steps.wasmtime-version.outputs.version }} is always installed, rather than letting any preinstalled wasmtime on the runner image silently satisfy the check. ~/.wasmtime/bin is prepended to $GITHUB_PATH, so the pinned install shadows any system-wide binary for the rest of the job.

Bump the six edgezero crates from e7887140 to dfb00b39, pulling in the
round-2 through round-4 review-feedback commits on PR #257:

- strict-clippy: address PR review feedback (round 2)
- strict-clippy: cloudflare scaffold + handlers.md doc fixes
- Bump redb 4.0 -> 4.1.0 (#255)
- merge main into chore/strict-clippy
- strict-clippy: round-4 review feedback (test.yml, cli logger, docs)

These touch edgezero-core (app.rs, error.rs, key_value_store.rs),
edgezero-macros (app.rs), and the fastly/cloudflare adapters. Lock-only
change; no mocktioneer source edits required.

Verified green: cargo check / clippy (-D warnings) / 161 tests / fmt /
"fastly cloudflare spin" feature build / all three wasm-target builds.
Fastly and Spin wasm contract tests pass via Viceroy and Wasmtime.
@prk-Jr prk-Jr self-requested a review June 12, 2026 07:32
prk-Jr
prk-Jr previously approved these changes Jun 12, 2026
stackpop/edgezero#257 (strict-clippy + defensive-coding pass) merged to
edgezero main as 7ec2ad1, and the chore/strict-clippy branch was deleted.
Switch all six edgezero crates from `branch = "chore/strict-clippy"` to
`branch = "main"` and re-resolve the lock onto 7ec2ad1.

Lock + manifest only; no mocktioneer source changes. Verified green:
cargo check / clippy (-D warnings) / 161 tests / fmt /
"fastly cloudflare spin" feature build / all three wasm-target builds.
@aram356 aram356 merged commit b96d973 into main Jun 12, 2026
13 checks passed
@aram356 aram356 deleted the chore/edgezero-strict-clippy branch June 12, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adopt edgezero strict-clippy gate and PR #257 API

3 participants