Skip to content

chore(security): sweep Dependabot advisories#198

Open
drewstone wants to merge 1 commit into
mainfrom
chore/security-sweep-tnt-core
Open

chore(security): sweep Dependabot advisories#198
drewstone wants to merge 1 commit into
mainfrom
chore/security-sweep-tnt-core

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Problem

26 open Dependabot alerts across the Rust workspace and four npm projects (mix of critical/high/medium/low).

Solution — deps bumped

Rust (Cargo.lock)

  • keccak 0.1.5 → 0.2.0 (RUSTSEC-2026-0012)
  • lru 0.13.0 → 0.16.4 — required bumping the parent alloy 1.1.2 → 1.8.3 (alloy-provider 1.4.0+ moves lru pin ^0.13^0.16)
  • quinn-proto 0.11.14 → 0.11.16 (bonus, pulled by cargo update)

npm — indexer/ (pnpm)

  • vitest 3.2.4 → 4.1.9 (direct; clears the critical vitest + shell-quote transitive advisories)
  • pnpm.overrides refreshed (were stale, pinning still-vulnerable versions): vite 6.4.3, ws 8.21.0/7.5.11, esbuild 0.28.1, qs 6.15.2, cookie 0.7.2, send 0.19.2, serve-static 1.16.3, express 4.22.1

npm — apps/claim-relayer/ (pnpm): same override set applied (ws, qs, cookie, send, serve-static, express, esbuild)

npm — packages/migration-claim/scripts + packages/credits/scripts (npm): ws override → ^8.21.0; viem 2.43.2 → 2.54.3 (also cleared a moderate viem advisory)

Alerts cleared vs unfixable

  • Cleared: 24 / 26. pnpm audit / npm audit report 0 vulnerabilities in all four npm projects; cargo audit clears keccak + lru (remaining cargo-audit output is unmaintained-crate warnings — derivative/paste/proc-macro-error2 — not in the Dependabot set, no patch).
  • Unfixable (2):

Build status — PASS

  • Rust: cargo check --workspace --all-features PASS on stable (1.96; CI uses dtolnay/rust-toolchain@stable, which satisfies alloy 1.8.3's rustc ≥1.91 requirement).
  • indexer: tsc --noEmit PASS (after envio codegen); vitest run 8/8 tests pass under vitest 4.
  • claim-relayer: tsc --noEmit PASS.
  • migration-claim/credits scripts: transpile-check 0 errors against viem 2.54 (ts-node/tsx runners, no tsc gate).

Protocol is not live; breaking dependency bumps are acceptable.

Rust (Cargo.lock): keccak 0.1.5->0.2.0, lru 0.13.0->0.16.4 (via alloy 1.1.2->1.8.3), quinn-proto 0.11.14->0.11.16.
npm: indexer vitest 3.2.4->4.1.9 + overrides (vite 6.4.3, ws 8.21.0, qs 6.15.2, esbuild 0.28.1, cookie 0.7.2, send 0.19.2, serve-static 1.16.3, express 4.22.1); claim-relayer same override set; migration-claim/credits scripts ws 8.21.0 + viem 2.43->2.54.
Unfixable: p3-symmetric (no patch), p3-challenger (SP1 6.1.0 pins 0.3.2-succinct; needs major sp1-sdk upgrade).

@tangletools tangletools 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.

✅ Auto-approved drewstone PR — 44d42582

This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: drewstone_author · 2026-07-04T21:36:44Z

@tangletools tangletools 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.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 2 (1 medium-concern, 1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 216.8s (2 bridge agents)
Total 216.8s

💰 Value — sound-with-nits

Clears 24/26 Dependabot advisories via standard lockfile-only Rust bumps and npm override refreshes — coherent and in-grain, but the alloy 1.1→1.8 jump silently raises the published bindings crate's MSRV from 1.81 to 1.91 without updating the declared rust-version.

  • What it does: Bumps vulnerable transitive deps to clear Dependabot advisories. Rust: keccak 0.1.5→0.2.0, lru 0.13→0.16.4 (requires alloy 1.1.2→1.8.3 because alloy-provider 1.4+ moved its lru pin), quinn-proto 0.11.14→0.11.16, and tiny-keccak is dropped. npm: indexer vitest 3.2.4→4.1.9 (direct dep, clears the critical vitest+shell-quote chain); pnpm.overrides refreshed across indexer and claim-relayer (vite 6.4.
  • Goals it achieves: Reduce security exposure to known-vulnerable transitive dependencies across the Rust workspace and four npm projects. The system is strictly better after merge: 24 of 26 Dependabot alerts cleared, npm audit reports zero in all four projects, and cargo-audit clears the keccak+lru entries. The remaining cargo-audit noise is unmaintained-crate warnings (derivative/paste/proc-macro-error2) outside the
  • Assessment: The approach is textbook dep-security hygiene and fits the codebase grain. The Rust side is lockfile-only — no Cargo.toml changes needed because bindings/Cargo.toml:27 already declares alloy = "1.0.35" (i.e. ^1.0.35), which permits 1.8.3; cargo update resolved within the already-declared semver range. The npm side uses the standard pnpm.overrides + npm overrides mechanism for transitive patchi
  • Better / existing approach: No materially better approach for the npm side. For Rust, an intermediate alloy 1.4.x pin (the minimum that unblocks lru 0.16) would reduce transitive churn — the 1.1→1.8 jump adds 53 net-new crates including aws-lc-rs/aws-lc-sys (native cmake/cc build), jni/jni-sys (Android bindings), and arkworks crypto — but cargo naturally resolves to latest-within-range and pinning to an intermediate would be
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 2
  • Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content

🎯 Usefulness — error

usefulness agent produced no parseable value-audit JSON.

  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1
  • Bridge error: no parseable JSON response

💰 Value Audit

🟠 alloy 1.8.3 raises actual MSRV to 1.91 but bindings/Cargo.toml still declares rust-version = "1.81" [maintenance] ``

Verified: bindings/Cargo.toml:5 declares rust-version = "1.81" and fixtures/Cargo.toml:5 declares the same. alloy 1.8.3 (now in Cargo.lock:2377 area) requires rustc 1.91 — confirmed by cargo check failing with 'alloy-consensus@1.8.3 requires rustc 1.91' (and 18 sibling alloy-* crates all requiring 1.91). This crate is published to crates.io as tnt-core-bindings v0.18.0 (no publish = false field), so downstream consumers relying on the declared MSRV 1.81 will break. Fix: bump rust-version

🟡 alloy 1.1→1.8 jump adds 53 net-new crates including aws-lc-sys (native build dep requiring cmake) [proportion] ``

Counted 54 added / 17 removed package entries in Cargo.lock. Notable additions: aws-lc-rs 1.17.1, aws-lc-sys 0.42.0 (pulls cmake, pkg-config, openssl-probe, jobserver), jni/jni-sys/jni-macros/jni-sys-macros (Android target of aws-lc-rs), ark-ff/ark-serialize/ark-std (arkworks), rustls-platform-verifier, secp256k1, secp256k1-sys. This is unavoidable given the goal (lru 0.16 requires alloy ≥1.4, and the Cargo.toml's alloy = "1.0.35" already permits 1.8.3), but it materially increases clean-build


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260704T214316Z

@tangletools

Copy link
Copy Markdown
Contributor

❌ Needs Work — 44d42582

Review health 100/100 · Reviewer score 27/100 · Confidence 95/100 · 22 findings (1 high, 3 medium, 18 low)

glm deepseek aggregate
Readiness 27 51 27
Confidence 95 95 95
Correctness 27 51 27
Security 27 51 27
Testing 27 51 27
Architecture 27 51 27

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 7/7 planned shots over 9 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 7/7 planned shots over 9 changed files. Global verifier still owns final merge decision.

Blocking

🔴 HIGH Lockfile MSRV (1.91) exceeds declared rust-version="1.81" in bindings/Cargo.toml — Cargo.lock

The updated lock pins alloy 1.8.3 (rust-version=1.91, 20 crates), alloy-eip7928 0.3.7 + ruint 1.19.0 (1.90), enum-ordinalize 4.4.1 (1.89), darling 0.23.0 (1.88). Verified via cargo metadata --locked | rust_version that max locked MSRV is 1.91. bindings/Cargo.toml:5 still declares rust-version="1.81". A consumer building tangle-bindings on Rust 1.81-1.90 (the declared-supported range) will hit 'rustc X.Y is unsupported' compile errors from alloy/ruint. Fix: either pin alloy to a <=1.81-compatible release (e.g. alloy ~1.0.x with appropriate transitive caps) OR bump rust-version in bindings/Cargo.toml and fixtures/Cargo.toml to "1.91" and document the MSRV bump in the crate's README/changelog since bindings is a published library consumed externally.

Other

🟠 MEDIUM TLS trust root switched from webpki-roots to rustls-platform-verifier (OS native store) — Cargo.lock

reqwest jumped 0.12.24 -> 0.13.4 inside alloy's transitive tree. reqwest 0.13 replaced the bundled webpki-roots Mozilla root store with rustls-platform-verifier, which delegates to the OS trust store (Keychain on macOS, /etc/ssl/certs on Linux, Windows cert store). For a published library this is a behavior change for any RPC/HTTPS path: trust decisions now vary by host OS configuration and any locally-installed CA will be trusted. webpki-roots is fully removed from the lock. If deterministic/cross-platform trust is desired, pin reqwest to 0.12 in bindings/Cargo.toml or add rustls 0.23 with the ring provider explicitly. Otherwise acceptable but should be a conscious decision, not an accidental cargo update side effect.

🟠 MEDIUM rustls crypto backend switched from ring to aws-lc-rs — Cargo.lock

rustls 0.23.35→0.23.41 drops the 'ring' dependency and adopts 'aws-lc-rs' as the default crypto provider. aws-lc-sys (v0.42.0) requires cmake + a C compiler to build (deps: cc, cmake, pkg-config). The bindings crate depends on alloy→alloy-rpc-client→reqwest→rustls for Ethereum RPC transport. This is a build-environment requirement change: environments without cmake installed (e.g., minimal Docker images) will fail cargo build --locked. Verify CI has cmake available, or configure rustls to use the ring backend via Cargo features if native compilation is problematic.

🟠 MEDIUM esbuild pre-1.0 minor version bump onto tsx via override — apps/claim-relayer/pnpm-lock.yaml

Override esbuild@>=0.27.0 <0.28.1: 0.28.1 forces tsx@4.21.0 to use esbuild 0.28.1 instead of its expected 0.27.2. esbuild follows pre-1.0 semver where minor versions MAY include breaking changes (esbuild 0.28.0 introduced breaking changes). tsx 4.21.0 was developed and tested only against the 0.27.x line. If esbuild 0.28.1 changed its transform API, decorator handling, or node: protocol resolution, tsx may fail to transpile TypeScript in dev mode (tsx src/index.ts would crash). Impact is limited to developer workflow (tsx is a devDependency, not used in production builds). Verify that tsx runs correctly with esbuild 0.28.1 before merging, or narrow the override to target only the specific esbuild version(s) that have a verified advisory.

🟡 LOW Lockfile format version bumped 3 -> 4 — Cargo.lock

The version = 4 field at the top of Cargo.lock indicates the file was regenerated by cargo >= 1.89 (cargo 1.88 writes v3). Contributors still on cargo 1.87/1.88 will auto-migrate on next build but may see spurious diffs. Not blocking — just ensure CI uses a recent stable toolchain (>= 1.91 to satisfy the MSRV finding above).

🟡 LOW alloy ecosystem upgraded 7 minor versions (1.1.2 → 1.8.3) — Cargo.lock

The alloy meta-crate and all its sub-crates (alloy-consensus, alloy-contract, alloy-network, alloy-provider, alloy-rpc-*, alloy-signer, etc.) jumped from ~1.1.2 to ~1.8.3. This is a large semver-compatible bump driven by cargo update resolving the alloy = { version = "1.0.35" } spec in bindings/Cargo.toml. New sub-crates like alloy-eip7928 appeared. While alloy's 1.x semver contract should prevent breakage, 7 minor versions is a wide surface area — verify cargo test --locked passes and that the xtask gen-bindings workflow produces identical output.

🟡 LOW aws-lc-sys adds cmake + pkg-config build-time requirements — Cargo.lock

rustls 0.23.41 now defaults to the aws-lc-rs crypto provider, pulling aws-lc-sys 0.42.0 which compiles AWS's C/C++ crypto lib via cmake 0.1.58, pkg-config 0.3.33, fs_extra 1.3.0, dunce 1.0.5, and cc 1.x. This adds hard build dependencies on cmake and a C/C++ toolchain that contributors and CI images must have installed; cross-compilation becomes more fragile. aws-lc itself is legitimate (same library used by AWS SDK, s2n, rustls default). Not a blocker, but CI Dockerfiles / contributor docs should be updated to ensure cmake is present. If avoiding the C build is preferred, force rustls to the ring provider via feature flags in dependent crates.

🟡 LOW reqwest 0.12 → 0.13 removes serde_urlencoded and webpki-roots — Cargo.lock

reqwest 0.12.24→0.13.4 drops serde_urlencoded and webpki-roots from its dependency tree, replacing them with internal form handling and rustls-platform-verifier/webpki-root-certs for TLS. If any workspace crate directly calls reqwest form-serialization APIs that relied on serde_urlencoded behavior, or imports webpki-roots types, compilation may break. The workspace member packages/migration-claim/sp1/prover-api/Cargo.toml explicitly pins reqwest = "0.12" and rustls = { version = "0.23", features = ["ring"] } but is NOT a top-level workspace member, so its constraints do not apply to this lockfile. Re-check if that crate is intended to share this lockfile.

🟡 LOW syn-solidity Solidity parser updated 1.4.1 → 1.6.0 — Cargo.lock

syn-solidity is the alloy Solidity ABI/type parser used by alloy-sol-types. The bindings crate (bindings/Cargo.toml) depends on alloy-sol-types 1.2.1 which transitively uses syn-solidity for code generation. While this is a semver-minor bump (1.4→1.6) and should be backward-compatible, any behavioral change in Solidity parsing could subtly affect the generated Rust bindings. Verify cargo test --locked and diff the generated bindings against the previous lockfile to confirm no regressions in the contract ABI bindings.

🟡 LOW esbuild override is out of scope for a runtime Express app — apps/claim-relayer/package.json

esbuild is a build/bundler tool, not a runtime dependency. A claim-relayer Express app pulling esbuild transitively is unusual. Adding a pnpm override for esbuild@>=0.27.0 <0.28.1 to 0.28.1 is harmless but suggests the overrides may have been bulk-copied from another project without trimming irrelevant entries. No functional impact, but adds unnecessary maintenance surface.

🟡 LOW isows peerDependencies lockfile recording format change — apps/claim-relayer/pnpm-lock.yaml

The isows@1.0.7 package entry in the lockfile changed its recorded peerDependencies from ws: '*' (the actual package.json declaration) to ws: 8.21.0 (the resolved version). Both base and head use lockfileVersion 9.0. This is a lockfile generation format difference between pnpm v9 minor versions — pnpm v9.15+ records resolved peer dep versions in the package entry. Not a functional issue; dependency resolution is unaffected since pnpm uses the snapshot entries (isows@1.0.7(ws@8.21.0)) for actual resolution. Informational only — confirms the lockfile was regenerated with pnpm and is internally consistent.

🟡 LOW isows peerDependency pinned to exact ws version in lockfile — apps/claim-relayer/pnpm-lock.yaml

Lockfile now records isows@1.0.7 peerDependencies as ws: 8.21.0 (was ws: '*'). The package's integrity hash is unchanged, so this is pnpm recording the resolved peer rather than a republished package — not a defect. Side effect: a future pnpm update ws will not flow through isows unless the override range is widened, so the lockfile is marginally more rigid than upstream intends. No action required for merge; flag for awareness only.

🟡 LOW Vitest 3 → 4 major bump has no in-shot test-pass evidence — indexer/package.json

vitest jumps from ^3.2.4 to ^4.1.9 (major). Vitest 4 changed default pool behavior, snapshot format, and dropped Node <18. Current usage is safe (minimal config, only describe/expect/it, Node>=22), but the shot provides no proof that pnpm test runs green post-bump. Recommend CI confirm pnpm test:unit passes on the new version before merge; if snapshots exist anywhere, expect a snapshot-format re-generation.

🟡 LOW npm-style overrides not fully synced with pnpm.overrides — indexer/package.json

The overrides section lacks entries for cookie, send, and serve-static that were added to pnpm.overrides. Additionally, overrides has blanket esbuild: "0.25.12" and ws: "8.21.0" whereas pnpm.overrides uses version-specific ranges for esbuild (0.25.12 for <=0.24.2, 0.28.1 for 0.27.x) and ws (7.5.11 for v7, 8.21.0 for v8). Since pnpm.overrides takes precedence in pnpm, this is functionally harmless, but the divergence between the two override sections reduces clarity and could confuse future maintainers or tools that read only the npm-style overrides field.

🟡 LOW pnpm.overrides vs npm overrides inconsistency for esbuild and ws — indexer/package.json

pnpm.overrides uses two scoped selectors for esbuild (esbuild@<=0.24.2: 0.25.12 AND esbuild@>=0.27.0 <0.28.1: 0.28.1) and two for ws (ws@>=8.0.0 <8.21.0: 8.21.0 AND ws@>=7.0.0 <7.5.11: 7.5.11), but the top-level npm overrides block pins single versions (esbuild: 0.25.12, ws: 8.21.0). With npm this forces a transitive dep requiring esbuild ^0.27 to 0.25.12, and a dep requiring ws ^7 to 8.21.0 — both can break installs or runtime under npm. The repo uses pnpm (test script is pnpm run test:unit), so impact is limited, but the inconsistency means npm install would behave differently. Either mirror the scoped selectors in npm overrides or drop the npm overrides block if pnpm is the only supported manager.

🟡 LOW vitest major version bump without visible test file changes in this shot — indexer/package.json

vitest bumped from ^3.2.4 to ^4.1.9 (major version). vitest 4.x introduced API changes (e.g., assertions moved, new onTestFinished/expect.poll patterns, vitest/config import changes). This shot only sees package.json — if other indexer test files in the PR handle the migration, this is fine. If no test code was updated and tests still pass, that's also fine (vitest 4.x may be backward-compatible for this project's test patterns). Verified: lockfile resolves vitest@4.1.9 with new @opentelemetry/api transitive dependency, node engines >=22 is satisfied.

🟡 LOW Node engine mismatch: indexer allows Node 23 but vitest 4 excludes it — indexer/pnpm-lock.yaml

indexer/package.json engines.node is ">=22.0.0" (admits Node 23), but vitest@4.1.9 engines is "^20.0.0 || ^22.0.0 || >=24.0.0" (excludes odd-numbered 23). A developer on Node 23 would hit an EBADENGINE warning from vitest 4. Low impact: Node 23 is non-LTS and uncommon in CI. Optional tighten: set engines.node to ">=22.0.0 <23 || >=24.0.0" or rely on .nvmrc.

🟡 LOW vitest major version bump needs test confirmation — indexer/pnpm-lock.yaml

vitest upgraded from 3.2.4 to 4.1.9 (major). The lockfile correctly resolves vitest 4 and its new transitive deps (@standard-schema/spec, obug, convert-source-map) while removing vitest 3 deps (cac, tinyspy, tinypool, strip-literal, js-tokens, check-error, deep-eql, loupe, pathval, debug@4.4.3). Verify that existing tests pass with vitest 4 — the API changed (vite-node no longer uses cac, spy no longer needs tinyspy, runner drops strip-literal).

🟡 LOW viem bumped 11 minor versions as a side effect of ws override — packages/credits/scripts/package-lock.json

The declared intent of this PR is a ws override ("ws": "^8.21.0"), but the lockfile also moves viem 2.43.2→2.54.3 and ox 0.10.6→0.14.30. The override alone would have forced ws to 8.21.0 inside the old viem without bumping viem itself; the viem/ox bumps are an incidental artifact of npm install re-resolving ^2.0.0 to latest. Impact is low because the scripts only use stable viem 2.x APIs (http transport, createPublicClient/createWalletClient, parseAbi, getAddress/isAddress, privateKeyToAccount) and never touch websocket transport, but a 11-minor jump in a financial-scripts package (publishRoot, runEpoch, computeEntitlements) deserves a runtime smoke (e.g. npm run compute-entitlements against a known fixture) before merge rather than relying on typecheck alone. Fix if risk-averse: p

🟡 LOW No runtime verification that scripts still execute after dep bump — packages/credits/scripts/package.json

The scripts block defines 5 operational entry points (generate-tree, compute-entitlements, run-epoch, publish-root, watch-claims) that handle Merkle-root publishing and on-chain transactions, but there is no test harness and no evidence in the diff that any of them were run after the viem/ox/ws bumps. Typecheck is necessary but not sufficient for viem, which has shipped subtle behavior changes in minor releases (e.g. error shapes, gas-estimation defaults). Recommend one of: add a npm run typecheck script + CI step, or run each script against a local anvil fixture and note the result in the PR.

🟡 LOW Deprecated @substrate/connect@0.8.11 (GPL-3.0-only) newly pinned in lockfile as optional transitive — packages/migration-claim/scripts/package-lock.json

@substrate/connect@0.8.11 is marked deprecated ('versions below 1.x are no longer maintained') and licensed GPL-3.0-only; its smoldot@2.0.26 child is GPL-3.0-or-later WITH Classpath-exception-2.0. These are optional transitives of @polkadot/api (not direct deps of this package) and were already in the graph at base — the lockfile just now materializes them after the viem/ws re-resolution. Since package.json has 'private: true' (internal operational scripts, not published/distributed), GPL-3.0-only does not contaminate a distributed artifact. No code change needed in this PR, but tracking issue warranted: consider bumping @polkadot/api to a version that drops or updates @substrate/connect, or adding an override to force @substrate/connect@1.x, to shed the deprecated GPL-3.0-only transitive.

🟡 LOW overrides block not reflected in lockfile root entry (npm quirk, override still effective) — packages/migration-claim/scripts/package-lock.json

The lockfile's root packages[""] entry lists only name/version/dependencies/devDependencies — no 'overrides' key, despite package.json declaring overrides for both uuid (^14.0.0) and ws (^8.21.0). Verified the overrides ARE effective: npm ls ws shows 8.21.0 deduped everywhere, npm ls uuid shows 14.0.0, and npm ci --package-lock-only reports no drift. npm omits the overrides key from the lockfile root when the forced version already matches natural resolution. No action required — documenting so a future reviewer doesn't flag the apparent mismatch as a bug.


tangletools · 2026-07-04T21:55:08Z · trace

@tangletools tangletools 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.

❌ 1 Blocking Finding — 44d42582

Full multi-shot audit completed 7/7 planned shots over 9 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 7/7 planned shots over 9 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-04T21:55:08Z · immutable trace

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.

2 participants