Skip to content

test(bench): add dataplane full-cycle benchmarks#274

Merged
NLipatov merged 15 commits intomainfrom
codex/add-dataplane-benchmarks-readme
Mar 16, 2026
Merged

test(bench): add dataplane full-cycle benchmarks#274
NLipatov merged 15 commits intomainfrom
codex/add-dataplane-benchmarks-readme

Conversation

@NLipatov
Copy link
Owner

@NLipatov NLipatov commented Mar 15, 2026

Summary by CodeRabbit

  • Documentation

    • Added a Performance section to the README and a Benchmarks data snapshot with sample results and reproduction notes; added a Benchmarks navbar link.
  • Documentation (UI)

    • New Benchmarks dashboard page, visual refresh (hero, cards, CTAs), updated site theming and responsive styles, and expanded internationalized copy across locales.
  • Tests

    • Added comprehensive benchmark suites for dataplane (UDP/TCP, single & parallel peers), egress sending, and repository lookup scenarios.

@NLipatov NLipatov self-assigned this Mar 15, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea024695-a9d1-48fb-97f3-bf7ca5f6a94d

📥 Commits

Reviewing files that changed from the base of the PR and between de4c48f and 13cfecf.

📒 Files selected for processing (1)
  • docs/TunGo/i18n/ja/code.json

📝 Walkthrough

Walkthrough

Adds many new full‑cycle dataplane benchmarks (UDP/TCP, client & server), egress and repository benchmarks, a static Benchmarks dashboard and dataset, homepage/features/footer UI and theming updates, extensive i18n additions, and a Performance section in the README — changes are tests, docs, assets, and styling only.

Changes

Cohort / File(s) Summary
ReadMe & Nav
ReadMe.md, docs/TunGo/docusaurus.config.js
Added Performance/Benchmarks documentation and a Benchmarks navbar item.
Benchmarks Page & Data
docs/TunGo/src/data/benchmarks.js, docs/TunGo/src/pages/benchmarks.js, docs/TunGo/src/pages/benchmarks.module.css
New static benchmark snapshot, Benchmarks React page with sparklines/metric cards/tables, and page styles.
Homepage / Hero
docs/TunGo/src/pages/index.js, docs/TunGo/src/pages/index.module.css
Reworked hero into a two‑column layout, added benchmarks CTA, and updated responsive styles.
Features Component & Styles
docs/TunGo/src/components/features/index.js, docs/TunGo/src/components/features/styles.module.css
Feature component refactored into linkable card with new props (to, external) and card visuals/responsive CSS.
Footer & Theming
docs/TunGo/src/components/footer/footer.js, docs/TunGo/src/components/footer/footer.module.css, docs/TunGo/src/css/custom.css
Footer text internationalized; many site CSS variables, navbar spacing, and footer/style polish added.
i18n: Navbar & Copy
docs/TunGo/i18n/*/docusaurus-theme-classic/navbar.json, docs/TunGo/i18n/*/code.json
Added Benchmarks navbar translations and a large set of new/updated translation keys for homepage, benchmarks, and footer across many locales.
UDP ChaCha20 Benchmarks (client/server)
src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go, src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go
New end‑to‑end UDP ChaCha20 benchmark tests, helpers, single and parallel peer scenarios.
TCP ChaCha20 Benchmarks (client/server)
src/infrastructure/tunnel/dataplane/client/tcp_chacha20/full_cycle_benchmark_test.go, src/infrastructure/tunnel/dataplane/server/tcp_chacha20/full_cycle_benchmark_test.go
New TCP ChaCha20 full‑cycle benchmarks with handshake/crypto builders, packet sinks, ingress handlers, and multi‑size payload runs.
Egress Benchmarks
src/application/network/connection/egress_benchmark_test.go
Benchmarks for DefaultEgress.SendDataIP (serial and parallel) with test stubs across payload sizes.
Session Repository Benchmarks
src/infrastructure/tunnel/session/repository_benchmark_test.go
Benchmarks for DefaultRepository lookups: exact internal, allowed host, miss, and GetByRouteID across varying repo sizes.

Sequence Diagram(s)

sequenceDiagram
    rect rgba(200,220,255,0.5)
    participant Bench as BenchHarness
    participant Repo as Repository
    participant Client as ClientCrypto
    participant Transport as TransportLayer
    participant Server as ServerCrypto
    participant Tun as TunWriter
    end
    Bench->>Repo: lookup peer by destination
    Repo-->>Bench: peer metadata
    Bench->>Client: build & encrypt IP payload
    Client-->>Transport: send encrypted frame
    Transport->>Server: deliver frame
    Server->>Server: decrypt & validate packet/header/epoch
    Server->>Repo: verify session/source
    Server-->>Tun: write decrypted payload
    Tun-->>Bench: ack/write success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through packets, keys in tow,
ChaCha twirled where datapaths grow,
Sparklines sparkled, peers in row,
Pages bloomed with throughput's glow,
A rabbit cheered the benchmark show.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.96% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary change: adding dataplane full-cycle benchmarks across multiple transport protocols and peer configurations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/add-dataplane-benchmarks-readme
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NLipatov NLipatov marked this pull request as ready for review March 15, 2026 16:23
@codecov
Copy link

codecov bot commented Mar 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 95.22% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go (2)

103-107: Partial struct initialization may break on production code changes.

The TransportHandler is constructed with only routeLookup, addrUpdater, and dp fields. Per the production constructor (context snippet 1), the full struct has additional fields: ctx, settings, writer, logger, listenerConn, and registrar. If handlePacket starts accessing any of these fields in the future, this benchmark will panic with nil dereference.

Consider adding a comment documenting which fields are required by handlePacket, or adding a minimal test-only constructor.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go`
around lines 103 - 107, The benchmark constructs TransportHandler with only
routeLookup, addrUpdater and dp which is brittle if handlePacket later uses
other fields; update the test to either (a) initialize the additional
TransportHandler fields used in production (ctx, settings, writer, logger,
listenerConn, registrar) with minimal no-op/test doubles or (b) add a small
test-only constructor (e.g. newTestTransportHandler) that documents and sets the
minimal required fields, and add a short comment on which fields handlePacket
depends on; reference TransportHandler, handlePacket and newUdpDataplaneWorker
when making the change.

130-132: Minor inconsistency: helper vs inline formatting.

This file uses benchmarkSizeName helper while TCP benchmarks use inline fmt.Sprintf("%dB", payloadSize). Consider using the same approach across all benchmark files for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go`
around lines 130 - 132, The helper function benchmarkSizeName(payloadSize int)
creates "%dB" strings but other benchmark files use inline fmt.Sprintf("%dB",
payloadSize); update this file for consistency by replacing uses of
benchmarkSizeName with inline fmt.Sprintf("%dB", payloadSize) and remove the
benchmarkSizeName function, or alternatively update the TCP benchmark files to
use the benchmarkSizeName helper—pick one approach and apply it project-wide so
formatting is consistent (reference: benchmarkSizeName).
src/infrastructure/tunnel/dataplane/client/tcp_chacha20/full_cycle_benchmark_test.go (1)

68-84: Consider adding IP header checksum if validation occurs.

The synthetic IPv4 packet has no header checksum (bytes 10-11 are zero). This is fine if the dataplane doesn't validate checksums, but could cause silent drops if any validation is added later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/client/tcp_chacha20/full_cycle_benchmark_test.go`
around lines 68 - 84, The synthetic IPv4 packet created by benchmarkIPv4Packet
lacks the IPv4 header checksum (bytes 10-11); compute the 16-bit ones‑complement
checksum over the 20‑byte header (treat bytes 10-11 as zero during computation)
and store the resulting checksum into packet[10] and packet[11] so the packet
validates if checksum checks are later enabled.
src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go (1)

104-107: Partial struct initialization - same concern as server UDP benchmark.

The TransportHandler is constructed with only writer and cryptographyService. The full struct (per context snippet 2) includes ctx, reader, rekeyController, handshakeCrypto, egress, and keepalive-related fields. Document dependencies or consider a test-only constructor.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go`
around lines 104 - 107, The TransportHandler in the test is only partially
initialized (writer, cryptographyService) while other required fields like ctx,
reader, rekeyController, handshakeCrypto, egress and keepalive-related fields
(e.g., keepaliveTicker/keepaliveWriter) are omitted; either fully populate those
fields in the test so the handler behaves like production (set ctx to
context.Background() or a cancellable context, provide a dummy reader, a
rekeyController mock, handshakeCrypto stub, egress channel/mocker, and any
keepalive fields) or add a small test-only constructor (e.g.,
NewTestTransportHandler) that accepts minimal dependencies and sets sane
defaults for ctx, reader, rekeyController, handshakeCrypto, egress and keepalive
internals; update the test to use that constructor and ensure TransportHandler
methods referenced in the test operate against those provided/mocked components.
src/infrastructure/tunnel/dataplane/server/tcp_chacha20/full_cycle_benchmark_test.go (1)

19-84: Significant code duplication with client TCP benchmark.

The benchmarkHandshake, benchmarkPacketSink, benchmarkTCPCryptoPair, and benchmarkIPv4Packet helpers are identical across all four benchmark files. Consider extracting these to a shared internal test package (e.g., internal/benchutil) to reduce maintenance burden and ensure consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/server/tcp_chacha20/full_cycle_benchmark_test.go`
around lines 19 - 84, Extract the duplicated helpers benchmarkHandshake,
benchmarkPacketSink, benchmarkTCPCryptoPair, and benchmarkIPv4Packet into a
shared internal test package (e.g., internal/benchutil) and update the benchmark
files to import and call those helpers; specifically, move the types and
functions Id, KeyClientToServer, KeyServerToClient, ServerSideHandshake,
ClientSideHandshake (from benchmarkHandshake), the Write method of
benchmarkPacketSink, benchmarkTCPCryptoPair (which builds
chacha.NewTcpSessionBuilder and calls FromHandshake), and benchmarkIPv4Packet
into the new package, make any necessary identifiers exported or provide
exported wrapper functions, then replace the local definitions in each of the
four benchmark files with calls to benchutil.BenchmarkTCPCryptoPair,
benchutil.BenchmarkIPv4Packet, etc., ensuring imports and tests compile.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/infrastructure/tunnel/dataplane/client/tcp_chacha20/full_cycle_benchmark_test.go`:
- Around line 68-84: The synthetic IPv4 packet created by benchmarkIPv4Packet
lacks the IPv4 header checksum (bytes 10-11); compute the 16-bit ones‑complement
checksum over the 20‑byte header (treat bytes 10-11 as zero during computation)
and store the resulting checksum into packet[10] and packet[11] so the packet
validates if checksum checks are later enabled.

In
`@src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go`:
- Around line 104-107: The TransportHandler in the test is only partially
initialized (writer, cryptographyService) while other required fields like ctx,
reader, rekeyController, handshakeCrypto, egress and keepalive-related fields
(e.g., keepaliveTicker/keepaliveWriter) are omitted; either fully populate those
fields in the test so the handler behaves like production (set ctx to
context.Background() or a cancellable context, provide a dummy reader, a
rekeyController mock, handshakeCrypto stub, egress channel/mocker, and any
keepalive fields) or add a small test-only constructor (e.g.,
NewTestTransportHandler) that accepts minimal dependencies and sets sane
defaults for ctx, reader, rekeyController, handshakeCrypto, egress and keepalive
internals; update the test to use that constructor and ensure TransportHandler
methods referenced in the test operate against those provided/mocked components.

In
`@src/infrastructure/tunnel/dataplane/server/tcp_chacha20/full_cycle_benchmark_test.go`:
- Around line 19-84: Extract the duplicated helpers benchmarkHandshake,
benchmarkPacketSink, benchmarkTCPCryptoPair, and benchmarkIPv4Packet into a
shared internal test package (e.g., internal/benchutil) and update the benchmark
files to import and call those helpers; specifically, move the types and
functions Id, KeyClientToServer, KeyServerToClient, ServerSideHandshake,
ClientSideHandshake (from benchmarkHandshake), the Write method of
benchmarkPacketSink, benchmarkTCPCryptoPair (which builds
chacha.NewTcpSessionBuilder and calls FromHandshake), and benchmarkIPv4Packet
into the new package, make any necessary identifiers exported or provide
exported wrapper functions, then replace the local definitions in each of the
four benchmark files with calls to benchutil.BenchmarkTCPCryptoPair,
benchutil.BenchmarkIPv4Packet, etc., ensuring imports and tests compile.

In
`@src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go`:
- Around line 103-107: The benchmark constructs TransportHandler with only
routeLookup, addrUpdater and dp which is brittle if handlePacket later uses
other fields; update the test to either (a) initialize the additional
TransportHandler fields used in production (ctx, settings, writer, logger,
listenerConn, registrar) with minimal no-op/test doubles or (b) add a small
test-only constructor (e.g. newTestTransportHandler) that documents and sets the
minimal required fields, and add a short comment on which fields handlePacket
depends on; reference TransportHandler, handlePacket and newUdpDataplaneWorker
when making the change.
- Around line 130-132: The helper function benchmarkSizeName(payloadSize int)
creates "%dB" strings but other benchmark files use inline fmt.Sprintf("%dB",
payloadSize); update this file for consistency by replacing uses of
benchmarkSizeName with inline fmt.Sprintf("%dB", payloadSize) and remove the
benchmarkSizeName function, or alternatively update the TCP benchmark files to
use the benchmarkSizeName helper—pick one approach and apply it project-wide so
formatting is consistent (reference: benchmarkSizeName).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f758610a-0af6-4e68-a745-2bb7dc6d0b1f

📥 Commits

Reviewing files that changed from the base of the PR and between 1aee334 and a345e00.

📒 Files selected for processing (5)
  • ReadMe.md
  • src/infrastructure/tunnel/dataplane/client/tcp_chacha20/full_cycle_benchmark_test.go
  • src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go
  • src/infrastructure/tunnel/dataplane/server/tcp_chacha20/full_cycle_benchmark_test.go
  • src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
src/infrastructure/tunnel/session/repository_benchmark_test.go (2)

117-121: Use errors.Is() for error comparison.

Direct equality comparison (err != ErrNotFound) works for this sentinel error but is inconsistent with Go idioms and the rest of the codebase. Using errors.Is() is more robust if the error is ever wrapped in the future.

♻️ Proposed fix
+import "errors"
+
 			for i := 0; i < b.N; i++ {
 				peer, err := repo.FindByDestinationIP(target)
-				if err != ErrNotFound || peer != nil {
+				if !errors.Is(err, ErrNotFound) || peer != nil {
 					b.Fatalf("expected miss, got peer=%v err=%v", peer, err)
 				}
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infrastructure/tunnel/session/repository_benchmark_test.go` around lines
117 - 121, The test currently compares the returned error from
repo.FindByDestinationIP using direct equality (err != ErrNotFound); change this
to use errors.Is(err, ErrNotFound) so wrapped errors are handled correctly —
update the condition in the benchmark loop to call errors.Is(err, ErrNotFound)
and keep the peer nil check, importing the errors package if not already
present; reference the repo.FindByDestinationIP call and the ErrNotFound
sentinel in repository_benchmark_test.go when making the change.

9-15: Address helpers are duplicated across benchmark files.

benchmarkIPv4Addr and benchmarkIPv4AddrPort appear in multiple test files. Consider extracting to a shared test utility package if more benchmark files are added.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/infrastructure/tunnel/session/repository_benchmark_test.go` around lines
9 - 15, Duplicate helpers benchmarkIPv4Addr and benchmarkIPv4AddrPort should be
extracted into a shared test utility package: create a test helper package
(e.g., package testutil) and move these functions there, make them exported
(e.g., BenchmarkIPv4Addr, BenchmarkIPv4AddrPort) if you place them in a
different package, then update benchmark files to import the helper package and
call testutil.BenchmarkIPv4Addr(...) and testutil.BenchmarkIPv4AddrPort(...);
ensure references to the original symbols are replaced and run tests to confirm
no import or visibility issues.
src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go (2)

204-231: Consider defer for unlock to prevent missed unlock paths.

The manual lock/unlock pattern with multiple error paths is fragile. While defer f.mu.Unlock() adds minor overhead (~5ns), it prevents potential deadlocks if future modifications add early returns. For benchmarks where this overhead matters, the current approach is acceptable—just be cautious when modifying this code.

♻️ Safer pattern with defer
 				for pb.Next() {
 					f.mu.Lock()
+					func() {
+						defer f.mu.Unlock()
 					addr, err := parser.DestinationAddress(f.packet)
 					if err != nil {
-						f.mu.Unlock()
 						b.Fatalf("parse destination: %v", err)
 					}
 					peer, err := repo.FindByDestinationIP(addr)
 					if err != nil {
-						f.mu.Unlock()
 						b.Fatalf("find peer: %v", err)
 					}
 					copy(sendBuf[prefixLen:], f.packet)
 					if err := peer.Egress().SendDataIP(sendBuf[:prefixLen+len(f.packet)]); err != nil {
-						f.mu.Unlock()
 						b.Fatalf("server encrypt/send: %v", err)
 					}
 					written, err := handler.handleDatagram(f.sink.buf)
 					if err != nil {
-						f.mu.Unlock()
 						b.Fatalf("client handle datagram: %v", err)
 					}
 					if written != len(f.packet) {
-						f.mu.Unlock()
 						b.Fatalf("unexpected payload length: got %d want %d", written, len(f.packet))
 					}
-					f.mu.Unlock()
+					}()
 				}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go`
around lines 204 - 231, The loop currently locks with f.mu.Lock() and manually
unlocks on every error path, which is fragile; change to call f.mu.Lock()
followed immediately by defer f.mu.Unlock() (inside the loop body) so the mutex
is always released even on early b.Fatalf/returns—ensure you remove the manual
f.mu.Unlock() calls after parser.DestinationAddress, repo.FindByDestinationIP,
peer.Egress().SendDataIP, handler.handleDatagram, and the final unlock to avoid
double-unlocking; keep the same operations (calling parser.DestinationAddress,
repo.FindByDestinationIP, peer.Egress().SendDataIP, handler.handleDatagram and
checking written) but rely on defer for unlocking.

21-92: Helper types and functions are duplicated with the server benchmark file.

The benchmarkHandshake, benchmarkPacketSink, benchmarkUDPCryptoPair, benchmarkIPv4Packet, and address helpers are nearly identical to those in src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go. Consider extracting these to a shared test utilities package (e.g., testutil or internal/benchutil) to reduce duplication and ease maintenance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go`
around lines 21 - 92, The file duplicates helper types and funcs
(benchmarkHandshake, benchmarkPacketSink, benchmarkUDPCryptoPair,
benchmarkIPv4Packet, benchmarkIPv4Addr, benchmarkIPv4AddrPort) already present
in the server benchmark; extract these into a shared test utilities package
(e.g., internal/benchutil or testutil) and import it from both benchmark files.
Move the type and function definitions to the new package, make any needed
symbols exported (or use the same package name in tests) so the client and
server benchmarks can call benchutil.BenchmarkUDPCryptoPair,
benchutil.BenchmarkIPv4Packet, etc., then replace the duplicated definitions in
both benchmark files with calls to the shared helpers and update imports. Ensure
builder/from-handshake usage (FromHandshake) and any dependencies (chacha,
chacha20poly1305) are accessible from the new package.
src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go (1)

20-91: Duplicated helpers with client benchmark file.

These helper types and functions are identical to those in src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go. Same refactoring suggestion applies—extract to a shared test utilities package.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go`
around lines 20 - 91, The file duplicates test helpers (types
benchmarkHandshake, benchmarkPacketSink and functions benchmarkUDPCryptoPair,
benchmarkIPv4Packet, benchmarkIPv4Addr, benchmarkIPv4AddrPort) already present
in the client benchmark; refactor by extracting these helpers into a shared test
utilities package (e.g., testutil) and replace the local definitions with
imports and calls to that package; update usages in both server and client
benchmark files to reference testutil.benchmarkHandshake,
testutil.benchmarkPacketSink, testutil.benchmarkUDPCryptoPair,
testutil.benchmarkIPv4Packet, testutil.benchmarkIPv4Addr, and
testutil.benchmarkIPv4AddrPort and adjust imports accordingly so both benchmarks
reuse the single implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go`:
- Around line 204-231: The loop currently locks with f.mu.Lock() and manually
unlocks on every error path, which is fragile; change to call f.mu.Lock()
followed immediately by defer f.mu.Unlock() (inside the loop body) so the mutex
is always released even on early b.Fatalf/returns—ensure you remove the manual
f.mu.Unlock() calls after parser.DestinationAddress, repo.FindByDestinationIP,
peer.Egress().SendDataIP, handler.handleDatagram, and the final unlock to avoid
double-unlocking; keep the same operations (calling parser.DestinationAddress,
repo.FindByDestinationIP, peer.Egress().SendDataIP, handler.handleDatagram and
checking written) but rely on defer for unlocking.
- Around line 21-92: The file duplicates helper types and funcs
(benchmarkHandshake, benchmarkPacketSink, benchmarkUDPCryptoPair,
benchmarkIPv4Packet, benchmarkIPv4Addr, benchmarkIPv4AddrPort) already present
in the server benchmark; extract these into a shared test utilities package
(e.g., internal/benchutil or testutil) and import it from both benchmark files.
Move the type and function definitions to the new package, make any needed
symbols exported (or use the same package name in tests) so the client and
server benchmarks can call benchutil.BenchmarkUDPCryptoPair,
benchutil.BenchmarkIPv4Packet, etc., then replace the duplicated definitions in
both benchmark files with calls to the shared helpers and update imports. Ensure
builder/from-handshake usage (FromHandshake) and any dependencies (chacha,
chacha20poly1305) are accessible from the new package.

In
`@src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go`:
- Around line 20-91: The file duplicates test helpers (types benchmarkHandshake,
benchmarkPacketSink and functions benchmarkUDPCryptoPair, benchmarkIPv4Packet,
benchmarkIPv4Addr, benchmarkIPv4AddrPort) already present in the client
benchmark; refactor by extracting these helpers into a shared test utilities
package (e.g., testutil) and replace the local definitions with imports and
calls to that package; update usages in both server and client benchmark files
to reference testutil.benchmarkHandshake, testutil.benchmarkPacketSink,
testutil.benchmarkUDPCryptoPair, testutil.benchmarkIPv4Packet,
testutil.benchmarkIPv4Addr, and testutil.benchmarkIPv4AddrPort and adjust
imports accordingly so both benchmarks reuse the single implementation.

In `@src/infrastructure/tunnel/session/repository_benchmark_test.go`:
- Around line 117-121: The test currently compares the returned error from
repo.FindByDestinationIP using direct equality (err != ErrNotFound); change this
to use errors.Is(err, ErrNotFound) so wrapped errors are handled correctly —
update the condition in the benchmark loop to call errors.Is(err, ErrNotFound)
and keep the peer nil check, importing the errors package if not already
present; reference the repo.FindByDestinationIP call and the ErrNotFound
sentinel in repository_benchmark_test.go when making the change.
- Around line 9-15: Duplicate helpers benchmarkIPv4Addr and
benchmarkIPv4AddrPort should be extracted into a shared test utility package:
create a test helper package (e.g., package testutil) and move these functions
there, make them exported (e.g., BenchmarkIPv4Addr, BenchmarkIPv4AddrPort) if
you place them in a different package, then update benchmark files to import the
helper package and call testutil.BenchmarkIPv4Addr(...) and
testutil.BenchmarkIPv4AddrPort(...); ensure references to the original symbols
are replaced and run tests to confirm no import or visibility issues.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f22add5-80cd-4478-a1b5-34befb83bdcf

📥 Commits

Reviewing files that changed from the base of the PR and between a345e00 and c644141.

📒 Files selected for processing (4)
  • src/application/network/connection/egress_benchmark_test.go
  • src/infrastructure/tunnel/dataplane/client/udp_chacha20/full_cycle_benchmark_test.go
  • src/infrastructure/tunnel/dataplane/server/udp_chacha20/full_cycle_benchmark_test.go
  • src/infrastructure/tunnel/session/repository_benchmark_test.go

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
docs/TunGo/src/pages/index.module.css (1)

64-72: Include -webkit-backdrop-filter in the @supports query for Safari compatibility.

The proposed @supports check only tests the unprefixed property. Since your browser targets include "last 5 safari version," you need to gate both the unprefixed and -webkit- variants together. Additionally, blur(14px) is on the high end of the recommended range; consider testing on lower-end devices before deploying, as backdrop-filter can be GPU-intensive.

♻️ Proposed change
 .heroPanel,
 .teaserShell,
 .teaserCard {
   border-radius: 28px;
   border: 1px solid var(--site-border);
   background: var(--site-surface);
   box-shadow: var(--site-shadow);
-  backdrop-filter: blur(14px);
 }
+
+@supports ((backdrop-filter: blur(14px)) or (-webkit-backdrop-filter: blur(14px))) {
+  .heroPanel,
+  .teaserShell,
+  .teaserCard {
+    -webkit-backdrop-filter: blur(14px);
+    backdrop-filter: blur(14px);
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/index.module.css` around lines 64 - 72, The `@supports`
check for backdrop-filter on the .heroPanel, .teaserShell, .teaserCard rules
only checks the unprefixed property; update the feature gate to test both
backdrop-filter and -webkit-backdrop-filter so Safari hits the same block, and
consider reducing blur(14px) to a lower value for performance testing on low-end
devices; target the rules around .heroPanel/.teaserShell/.teaserCard and the
backdrop-filter declaration to make these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/TunGo/src/pages/index.module.css`:
- Around line 64-72: The `@supports` check for backdrop-filter on the .heroPanel,
.teaserShell, .teaserCard rules only checks the unprefixed property; update the
feature gate to test both backdrop-filter and -webkit-backdrop-filter so Safari
hits the same block, and consider reducing blur(14px) to a lower value for
performance testing on low-end devices; target the rules around
.heroPanel/.teaserShell/.teaserCard and the backdrop-filter declaration to make
these changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 50dac674-89dd-489c-acc2-7c26e26cd511

📥 Commits

Reviewing files that changed from the base of the PR and between c644141 and b602126.

📒 Files selected for processing (10)
  • docs/TunGo/docusaurus.config.js
  • docs/TunGo/src/components/features/index.js
  • docs/TunGo/src/components/features/styles.module.css
  • docs/TunGo/src/components/footer/footer.module.css
  • docs/TunGo/src/css/custom.css
  • docs/TunGo/src/data/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
✅ Files skipped from review due to trivial changes (1)
  • docs/TunGo/src/pages/benchmarks.module.css

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
docs/TunGo/src/pages/benchmarks.js (1)

219-227: Derive these KPI cards from benchmarkSnapshot.

The other summary cards already read from the snapshot, but Lines 221 and 226 duplicate literal ranges. They'll drift as soon as the benchmark data file changes.

♻️ Suggested refactor
 export default function BenchmarksPage() {
   const bestFullCycle = [...benchmarkSnapshot.fullCycle1400].sort((a, b) => b.throughput - a.throughput)[0];
   const lowestLatency = [...benchmarkSnapshot.fullCycle1400].sort((a, b) => a.ns - b.ns)[0];
+  const fastPathNs = benchmarkSnapshot.repository.fastPath.flatMap((row) =>
+    row.series.map((point) => point.ns),
+  );
+  const fastPathRange = `${formatNs(Math.min(...fastPathNs))} – ${formatNs(Math.max(...fastPathNs))}`;
+  const egressRange = `${formatNs(benchmarkSnapshot.egress.uncontendedNs)} → ${formatNs(
+    benchmarkSnapshot.egress.contendedNs,
+  )}`;
 
   return (
@@
           <MetricCard
             label="Repository fast-path lookup"
-            value="~4-15 ns"
+            value={fastPathRange}
             note="Route ID, exact internal, and allowed-host hits stay flat through 10k peers"
           />
           <MetricCard
             label="Egress serialization cost"
-            value="~4.7 ns -> ~82 ns"
+            value={egressRange}
             note="From uncontended send path to contested parallel sends on one egress lane"
           />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/benchmarks.js` around lines 219 - 227, The two
MetricCard instances ("Repository fast-path lookup" and "Egress serialization
cost") are using hard-coded value strings; instead compute their value and note
text from the existing benchmarkSnapshot object used elsewhere on the page.
Locate the MetricCard components in this file and replace the literal value/
note props with expressions that read the corresponding fields from
benchmarkSnapshot (e.g., derive fast-path min/max ns and egress
contested/uncontended values), formatting them to the same "~x ns" style; ensure
you reference the same snapshot keys used by the other summary cards so these
metrics update automatically when benchmarkSnapshot changes.
docs/TunGo/src/components/features/styles.module.css (1)

141-156: Keep an explicit focus outline on the link.

Line 159 removes the native outline from the actual focusable element. The remaining indicator is mostly shadow/transform on a child node, which is less reliable in forced-colors/high-contrast modes.

🎯 Suggested tweak
 .featureCardLink:focus-visible {
-  outline: none;
+  outline: 2px solid var(--site-accent);
+  outline-offset: 4px;
 }
`@media` (forced-colors: active) {
  .featureCardLink:focus-visible {
    outline-color: Highlight;
  }
}

Also applies to: 158-160

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/components/features/styles.module.css` around lines 141 - 156,
The focus indicator relies only on child transforms/shadows and removes the
native outline on the focusable link; restore an explicit outline for
high-contrast/forced-colors modes by adding a forced-colors media rule for
.featureCardLink:focus-visible that sets an accessible outline (e.g., outline:
2px solid Highlight or at minimum outline-color: Highlight) so the link retains
a clear focus ring in forced-colors/high-contrast environments and ensure any
rule that strips the native outline from .featureCardLink on focus is removed or
scoped so it does not apply under forced-colors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/src/components/features/index.js`:
- Around line 37-43: The new hardcoded UI strings in the component (the
eyebrow/heading/paragraph inside the element using Styles.sectionIntro and other
labels between lines 45-92) must be wrapped with Docusaurus' Translate so they
are extractable for all locales; import Translate from '@docusaurus/Translate'
at the top, then replace plain string literals used in the Heading (component
named Heading), span with Styles.eyebrow, p with Styles.sectionText, and all
context/CTA labels ("Dataplane", "Benchmarks", "Footprint", "Cryptography",
"Quick start", "Repository", etc.) with <Translate>... strings (or
Translate.translate if inline) so each visible string is translatable. Ensure
you use the same identifiers (Styles.sectionIntro, Styles.eyebrow,
Styles.sectionTitle, Styles.sectionText, Heading) to locate the exact spots to
update.

In `@docs/TunGo/src/components/features/styles.module.css`:
- Line 5: Add a rule to the Stylelint config to ignore the CSS Modules :global()
pseudo-class so the selectors like :global(.container) no longer fail CI: update
.stylelintrc.json to configure the selector-pseudo-class-no-unknown rule to
allow the "global" pseudo-class (i.e., set selector-pseudo-class-no-unknown to
include ignorePseudoClasses: ["global"]) so lines using :global(...) in
styles.module.css and index.module.css pass linting.

In `@docs/TunGo/src/pages/benchmarks.js`:
- Around line 33-42: The sparkline x-position currently uses the sample index,
which misrepresents peer scaling; update the mapping in the series -> points
code (the block using series.map, valueKey, padding, innerWidth, innerHeight) to
compute x from point.peers instead: compute minPeers and maxPeers across series,
then map x = padding + innerWidth * ( (Math.log(point.peers || 1) -
Math.log(Math.max(1,minPeers))) / (Math.log(Math.max(1,maxPeers)) -
Math.log(Math.max(1,minPeers))) ); guard against peers <= 0 and when min==max
fall back to centered x, and if point.peers is missing keep the existing
index-based fallback or treat the chart as categorical.

---

Nitpick comments:
In `@docs/TunGo/src/components/features/styles.module.css`:
- Around line 141-156: The focus indicator relies only on child
transforms/shadows and removes the native outline on the focusable link; restore
an explicit outline for high-contrast/forced-colors modes by adding a
forced-colors media rule for .featureCardLink:focus-visible that sets an
accessible outline (e.g., outline: 2px solid Highlight or at minimum
outline-color: Highlight) so the link retains a clear focus ring in
forced-colors/high-contrast environments and ensure any rule that strips the
native outline from .featureCardLink on focus is removed or scoped so it does
not apply under forced-colors.

In `@docs/TunGo/src/pages/benchmarks.js`:
- Around line 219-227: The two MetricCard instances ("Repository fast-path
lookup" and "Egress serialization cost") are using hard-coded value strings;
instead compute their value and note text from the existing benchmarkSnapshot
object used elsewhere on the page. Locate the MetricCard components in this file
and replace the literal value/ note props with expressions that read the
corresponding fields from benchmarkSnapshot (e.g., derive fast-path min/max ns
and egress contested/uncontended values), formatting them to the same "~x ns"
style; ensure you reference the same snapshot keys used by the other summary
cards so these metrics update automatically when benchmarkSnapshot changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40c08938-a1cc-417e-9e77-7f5139a1e142

📥 Commits

Reviewing files that changed from the base of the PR and between b602126 and 76171d7.

📒 Files selected for processing (9)
  • ReadMe.md
  • docs/TunGo/src/components/features/index.js
  • docs/TunGo/src/components/features/styles.module.css
  • docs/TunGo/src/components/footer/footer.module.css
  • docs/TunGo/src/css/custom.css
  • docs/TunGo/src/pages/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/TunGo/src/pages/benchmarks.module.css
  • ReadMe.md

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
docs/TunGo/src/components/features/styles.module.css (1)

5-5: ⚠️ Potential issue | 🔴 Critical

Stylelint will fail on CSS Modules :global(...) selectors unless config is updated.

selector-pseudo-class-no-unknown is currently tripping on :global(...) usages (Line 5, Line 34, Line 65, Lines 95-96). Please fix at the config level so these valid CSS Modules selectors pass lint.

🔧 Proposed config fix
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@
 {
   "extends": [
     "stylelint-config-standard-scss"
   ],
+  "rules": {
+    "selector-pseudo-class-no-unknown": [
+      true,
+      { "ignorePseudoClasses": ["global"] }
+    ]
+  }
 }
#!/bin/bash
set -euo pipefail

echo "== stylelint configs =="
fd -HI '^\.stylelintrc(\.json|\.js|\.cjs|\.yaml|\.yml)?$|^stylelint\.config\.(js|cjs|mjs)$'

echo
echo "== verify selector-pseudo-class-no-unknown config =="
rg -n "selector-pseudo-class-no-unknown|ignorePseudoClasses|global" $(fd -HI '^\.stylelintrc(\.json|\.js|\.cjs|\.yaml|\.yml)?$|^stylelint\.config\.(js|cjs|mjs)$') || true

echo
echo "== :global() usages in CSS Modules =="
rg -n --glob '**/*.module.css' ':global\(' docs/TunGo/src

Also applies to: 34-34, 65-65, 95-96

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/components/features/styles.module.css` at line 5, Stylelint is
flagging CSS Modules :global(...) selectors in styles.module.css because the
selector-pseudo-class-no-unknown rule doesn't recognize the pseudo-class; update
your stylelint configuration to allow CSS Modules :global by adding "global" to
selector-pseudo-class-no-unknown.ignorePseudoClasses (or add a config override
for "**/*.module.css" that disables/adjusts selector-pseudo-class-no-unknown),
ensuring the rule name selector-pseudo-class-no-unknown and the :global(...)
usages in styles.module.css are referenced so :global selectors on lines 5, 34,
65, and 95–96 no longer error.
🧹 Nitpick comments (2)
docs/TunGo/src/pages/index.js (1)

34-35: Remove unused siteConfig extraction.

The siteConfig is extracted from context but never used. This appears to be leftover from a previous implementation.

♻️ Suggested fix
 export default function Home() {
-  const {siteConfig} = UseDocusaurusContext();
   return (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/index.js` around lines 34 - 35, The Home component
extracts siteConfig via "const {siteConfig} = UseDocusaurusContext();" but never
uses it; remove that unused extraction by deleting the "const {siteConfig} =
UseDocusaurusContext();" statement (or replace UseDocusaurusContext import/use
with a plain call if needed elsewhere) inside the Home function to eliminate the
dead variable and any unused import.
docs/TunGo/src/pages/benchmarks.js (1)

227-236: Consider deriving these values from data.

The "Fast-path lookup" value "~4-15 ns" and "Allocs/op" value "0" are hardcoded. If the benchmark data changes, these cards could become inconsistent with the actual results. Consider computing these from the data source for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/benchmarks.js` around lines 227 - 236, The MetricCard
props for "Fast-path lookup" and "Allocs/op" are hardcoded; update benchmarks.js
to compute these values from the benchmark data before rendering and pass the
computed strings into MetricCard.value (and adjust MetricCard.note if needed).
Locate where the rendered MetricCard instances are created and replace the
literal values "~4-15 ns" and "0" with derived variables (e.g.,
fastPathLookupValue and allocsPerOpValue) that are computed from the existing
benchmark results/summary object (the same data used to render other metrics) so
the cards always reflect current benchmark output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/src/pages/index.js`:
- Around line 23-25: The "View benchmarks" string inside the Link component in
pages/index.js is hardcoded; update the Link (the element using Clsx and
Styles.secondaryCta) to wrap that text with the <Translate> component (importing
Translate if not already) so the secondary CTA uses the same
internationalization as the primary CTA; ensure the import and the Link children
use <Translate id="...">View benchmarks</Translate> (use a descriptive id) to
match existing i18n patterns.

---

Duplicate comments:
In `@docs/TunGo/src/components/features/styles.module.css`:
- Line 5: Stylelint is flagging CSS Modules :global(...) selectors in
styles.module.css because the selector-pseudo-class-no-unknown rule doesn't
recognize the pseudo-class; update your stylelint configuration to allow CSS
Modules :global by adding "global" to
selector-pseudo-class-no-unknown.ignorePseudoClasses (or add a config override
for "**/*.module.css" that disables/adjusts selector-pseudo-class-no-unknown),
ensuring the rule name selector-pseudo-class-no-unknown and the :global(...)
usages in styles.module.css are referenced so :global selectors on lines 5, 34,
65, and 95–96 no longer error.

---

Nitpick comments:
In `@docs/TunGo/src/pages/benchmarks.js`:
- Around line 227-236: The MetricCard props for "Fast-path lookup" and
"Allocs/op" are hardcoded; update benchmarks.js to compute these values from the
benchmark data before rendering and pass the computed strings into
MetricCard.value (and adjust MetricCard.note if needed). Locate where the
rendered MetricCard instances are created and replace the literal values "~4-15
ns" and "0" with derived variables (e.g., fastPathLookupValue and
allocsPerOpValue) that are computed from the existing benchmark results/summary
object (the same data used to render other metrics) so the cards always reflect
current benchmark output.

In `@docs/TunGo/src/pages/index.js`:
- Around line 34-35: The Home component extracts siteConfig via "const
{siteConfig} = UseDocusaurusContext();" but never uses it; remove that unused
extraction by deleting the "const {siteConfig} = UseDocusaurusContext();"
statement (or replace UseDocusaurusContext import/use with a plain call if
needed elsewhere) inside the Home function to eliminate the dead variable and
any unused import.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71762983-18af-452a-ad25-b78aaa83781f

📥 Commits

Reviewing files that changed from the base of the PR and between 76171d7 and 90c58aa.

📒 Files selected for processing (9)
  • ReadMe.md
  • docs/TunGo/src/components/features/index.js
  • docs/TunGo/src/components/features/styles.module.css
  • docs/TunGo/src/css/custom.css
  • docs/TunGo/src/data/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
✅ Files skipped from review due to trivial changes (1)
  • docs/TunGo/src/css/custom.css
🚧 Files skipped from review as they are similar to previous changes (3)
  • ReadMe.md
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/data/benchmarks.js

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
docs/TunGo/i18n/ar/docusaurus-theme-classic/navbar.json (1)

1-14: Missing title and logo.alt translation keys.

The English reference file (docs/TunGo/i18n/en/docusaurus-theme-classic/navbar.json) includes title and logo.alt keys that are missing from this Arabic localization. Consider adding them for completeness:

{
  "title": {
    "message": "TunGo",
    "description": "The title in the navbar"
  },
  "logo.alt": {
    "message": "شعار TunGo",
    "description": "The alt text of navbar logo"
  },
  ...
}

This applies to all new locale files in this PR (fr, ru, zh-Hans, de, es). Docusaurus will fall back to the default locale if these are missing, but having them ensures full localization coverage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/ar/docusaurus-theme-classic/navbar.json` around lines 1 - 14,
Add the missing "title" and "logo.alt" translation keys to the navbar.json
locale files (e.g., the Arabic file shown) so they mirror the English reference;
create entries for "title" (message: "TunGo", description: "The title in the
navbar") and "logo.alt" (message: "شعار TunGo", description: "The alt text of
navbar logo") and apply the same addition to the other new locale navbar.json
files (fr, ru, zh-Hans, de, es) to ensure full localization coverage.
docs/TunGo/src/pages/index.module.css (1)

55-61: Stylelint errors are false positives — :global() is valid CSS Modules syntax.

The :global() pseudo-class is a standard CSS Modules feature used to escape local scoping, and Docusaurus explicitly supports this pattern. Consider adding a .stylelintrc rule to recognize :global if these warnings appear in CI:

{
  "rules": {
    "selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["global"] }]
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/index.module.css` around lines 55 - 61, Stylelint is
flagging the CSS Modules :global() pseudo-class in the selector ".buttons
:global(.button)"; add a Stylelint rule to allow the "global" pseudo-class so
these are not treated as unknown—update your Stylelint config (e.g.,
.stylelintrc or stylelint key in package.json) to set
"selector-pseudo-class-no-unknown" with an ignorePseudoClasses array including
"global" so the :global() usage is accepted by CI.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/src/components/footer/footer.js`:
- Around line 10-23: The footer component references missing translation IDs
(footer.iconsBy, footer.builtWith, footer.contributors) causing missing text for
all locales; add these three keys to each locale's i18n/{locale}/code.json with
appropriate translated strings (for locales en, fr, pt, ru, de, id, ja, zh-Hans,
es, ar) so the Translate calls in footer.js resolve correctly, ensuring you use
the exact ID names and place them under the same JSON structure used for other
translations in each file.

---

Nitpick comments:
In `@docs/TunGo/i18n/ar/docusaurus-theme-classic/navbar.json`:
- Around line 1-14: Add the missing "title" and "logo.alt" translation keys to
the navbar.json locale files (e.g., the Arabic file shown) so they mirror the
English reference; create entries for "title" (message: "TunGo", description:
"The title in the navbar") and "logo.alt" (message: "شعار TunGo", description:
"The alt text of navbar logo") and apply the same addition to the other new
locale navbar.json files (fr, ru, zh-Hans, de, es) to ensure full localization
coverage.

In `@docs/TunGo/src/pages/index.module.css`:
- Around line 55-61: Stylelint is flagging the CSS Modules :global()
pseudo-class in the selector ".buttons :global(.button)"; add a Stylelint rule
to allow the "global" pseudo-class so these are not treated as unknown—update
your Stylelint config (e.g., .stylelintrc or stylelint key in package.json) to
set "selector-pseudo-class-no-unknown" with an ignorePseudoClasses array
including "global" so the :global() usage is accepted by CI.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c56a51a4-4188-4cdb-8f53-ecb4b8b722c5

📥 Commits

Reviewing files that changed from the base of the PR and between 76171d7 and 327c253.

📒 Files selected for processing (20)
  • ReadMe.md
  • docs/TunGo/i18n/ar/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/de/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/en/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/es/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/fr/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/id/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/ja/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/pt/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/ru/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/zh-Hans/docusaurus-theme-classic/navbar.json
  • docs/TunGo/src/components/features/index.js
  • docs/TunGo/src/components/features/styles.module.css
  • docs/TunGo/src/components/footer/footer.js
  • docs/TunGo/src/css/custom.css
  • docs/TunGo/src/data/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.js
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
✅ Files skipped from review due to trivial changes (2)
  • docs/TunGo/i18n/ja/docusaurus-theme-classic/navbar.json
  • docs/TunGo/i18n/id/docusaurus-theme-classic/navbar.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/TunGo/src/data/benchmarks.js
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/benchmarks.js

Comment on lines +10 to +23
<Translate id="footer.iconsBy">Icons by</Translate>{' '}
<Link to="https://openmoji.org/" target="_blank" rel="noopener noreferrer">
OpenMoji
</Link>{' '}
(CC BY-SA 4.0)
</p>
<p>
Built with{' '}
<Translate id="footer.builtWith">Built with</Translate>{' '}
<Link to={"https://docusaurus.io/"} target={"_blank"} rel="noopener noreferrer">
Docusaurus
</Link>
</p>
<p>
©{new Date().getFullYear()} TunGo Contributors
©{new Date().getFullYear()} <Translate id="footer.contributors">TunGo Contributors</Translate>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if footer translation keys are defined across locales

# Find all code.json files and check for footer translation keys
echo "Checking for footer translation keys in locale files..."
fd 'code.json' docs/TunGo/i18n --exec sh -c 'echo "=== {} ===" && cat {} | grep -E "footer\.(iconsBy|builtWith|contributors)" || echo "No footer keys found"'

Repository: NLipatov/TunGo

Length of output: 698


Add missing footer translation keys to all locale files.

The translation IDs referenced in the component (footer.iconsBy, footer.builtWith, footer.contributors) are not defined in any of the locale files across all 10 supported locales (en, fr, pt, ru, de, id, ja, zh-Hans, es, ar). Add these keys with appropriate translations to i18n/{locale}/code.json for each locale, otherwise the footer will fail to display properly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/components/footer/footer.js` around lines 10 - 23, The footer
component references missing translation IDs (footer.iconsBy, footer.builtWith,
footer.contributors) causing missing text for all locales; add these three keys
to each locale's i18n/{locale}/code.json with appropriate translated strings
(for locales en, fr, pt, ru, de, id, ja, zh-Hans, es, ar) so the Translate calls
in footer.js resolve correctly, ensuring you use the exact ID names and place
them under the same JSON structure used for other translations in each file.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/src/pages/benchmarks.module.css`:
- Around line 124-150: The split layout prevents the fast-path table from
keeping its 760px width and blocks horizontal scrolling; update the CSS for
.splitSection/.splitTable/.tableWrap so the right column can host a fixed-width
table and scroll when viewport is narrow: remove or override min-width: 0 on
.splitTable, set .splitTable { overflow: auto; justify-self: end; } and make
.splitTable .tableWrap { min-width: 760px; width: 100%; overflow: auto; } (or
increase the grid-template-columns second column to accommodate min 760px, e.g.
grid-template-columns: minmax(240px,300px) minmax(760px, 1fr)). This works with
the existing DataTable wrapper (fastPathTable) so the table will stay 760px and
horizontally scroll below 996px instead of collapsing.

In `@docs/TunGo/src/pages/index.module.css`:
- Around line 20-25: The localized suffix is being forced on one line by the
combination of Styles.noBreak, the .heroBanner overflow:hidden rule, and a title
rule that shrinks to width: 11ch; to fix, remove/relax the no-break behavior
(stop applying white-space: nowrap in Styles.noBreak or only apply it to
non-localized parts), remove or change overflow:hidden in .heroBanner to allow
visible wrapping, and loosen the title width constraint (remove or increase the
width: 11ch rule) so translated suffixes can wrap naturally; update the CSS
selectors where Styles.noBreak, .heroBanner, and the title width rule are
defined.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0079088b-f020-4f46-926f-0083913939d6

📥 Commits

Reviewing files that changed from the base of the PR and between 327c253 and cc1744f.

📒 Files selected for processing (2)
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.module.css

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
docs/TunGo/src/components/features/styles.module.css (1)

5-5: ⚠️ Potential issue | 🔴 Critical

Unresolved Stylelint CI blocker for :global(...) selectors

Same issue as previously reported: Line 5 (also Lines 34, 65, 95, 96) will fail selector-pseudo-class-no-unknown unless Stylelint is configured to allow CSS Modules :global. Please fix the root config so these selectors pass lint.

Proposed config fix (.stylelintrc.json)
{
  "extends": [
    "stylelint-config-standard-scss"
  ],
+ "rules": {
+   "selector-pseudo-class-no-unknown": [
+     true,
+     { "ignorePseudoClasses": ["global"] }
+   ]
+ }
}
#!/bin/bash
set -euo pipefail

echo "== Stylelint config files =="
fd -a '(.stylelintrc.*|stylelint.config.*|package.json)$'

echo
echo "== selector-pseudo-class-no-unknown config =="
fd -a '(.stylelintrc.*|stylelint.config.*|package.json)$' \
  | xargs -I{} sh -c 'echo "-- {}"; rg -n "selector-pseudo-class-no-unknown|ignorePseudoClasses|global" "{}" || true'

echo
echo "== Remaining :global(...) usage in CSS Modules =="
fd -a '\.module\.css$' docs/TunGo/src \
  | xargs rg -n ':global\('

Expected: stylelint config includes ignorePseudoClasses: ["global"]; :global(...) usages remain valid without lint errors.

Also applies to: 34-34, 65-65, 95-96

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/components/features/styles.module.css` at line 5, The
Stylelint error is because CSS Modules uses the :global(...) pseudo which
selector-pseudo-class-no-unknown flags; update the Stylelint config to whitelist
the pseudo by adding ignorePseudoClasses: ["global"] under the
selector-pseudo-class-no-unknown rule so selectors like the .features
:global(.container) usages (and the other :global(...) occurrences) stop failing
lint; ensure the config change is applied to your active stylelint config file
so the rule recognizes the global pseudo across the project.
🧹 Nitpick comments (3)
docs/TunGo/src/pages/index.module.css (1)

55-61: Stylelint false positive: :global is valid CSS Modules syntax.

The :global(.button) selector is a standard CSS Modules feature for escaping local scope. The Stylelint error can be resolved by configuring the selector-pseudo-class-no-unknown rule to allow :global.

Example Stylelint configuration
{
  "rules": {
    "selector-pseudo-class-no-unknown": [
      true,
      { "ignorePseudoClasses": ["global", "local"] }
    ]
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/index.module.css` around lines 55 - 61, Stylelint is
flagging the ":global(.button)" selector in the .buttons :global(.button) rule
even though :global is valid CSS Modules syntax; update the Stylelint config to
allow the pseudo-classes by adding "global" (and "local") to the
selector-pseudo-class-no-unknown ignore list so the rule no longer reports false
positives for CSS Modules selectors like :global and :local.
docs/TunGo/i18n/de/code.json (2)

167-169: Mixed language in translation.

"Hot Path" is left in English while other technical terms are translated (e.g., "Durchsatz" for throughput). For consistency, consider either translating to German (e.g., "Kritischer Pfad") or keeping all technical terms in English throughout.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/de/code.json` around lines 167 - 169, The translation for the
key "bench.metric.allocsNote" currently uses the English phrase "Hot Path";
replace it with the consistent German translation (e.g., "Kritischer Pfad") or
adjust according to the project's i18n policy to keep technical terms in English
across the file, updating the "message" value for bench.metric.allocsNote
accordingly so it matches the rest of the German translations.

173-175: Awkward German-English mix.

"Von uncontended zu contended Sends" mixes English terms into a German sentence. Consider a fully German phrase like "Von unbelasteten zu belasteten Sendungen" or keeping the technical terms but improving flow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/de/code.json` around lines 173 - 175, The value for the i18n
key "bench.summary.egressNote" mixes English and German; replace the message
string with a fully German phrase (e.g., "Von unbelasteten zu belasteten
Sendungen") or an improved German technical phrasing if you want to keep terms
(e.g., "Von uncontended- zu contended-Sends" avoided) so that the
"bench.summary.egressNote" entry reads clearly in German and preserves meaning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/i18n/fr/code.json`:
- Line 15: Replace the incorrect metric unit in the French translation: locate
the JSON entry with key "message" whose value is "0 alloc/op sur le hot path."
and change "alloc/op" to the project-standard "allocs/op" so the string becomes
"0 allocs/op sur le hot path."; update the specific "message" value in the i18n
JSON accordingly.

In `@docs/TunGo/i18n/id/code.json`:
- Around line 65-67: The translation for the key "bench.section.scaling.title"
currently uses "Skalasi UDP multi-peer" which appears incorrect; update the
message value to a standard Indonesian term such as "Skalabilitas UDP
multi-peer" or "Penskalaan UDP multi-peer" by editing the
"bench.section.scaling.title" entry in the JSON so the value reads one of those
suggested phrases (choose the preferred term and replace the existing "message"
string).

In `@docs/TunGo/i18n/ja/code.json`:
- Around line 188-190: The footer.builtWith message is left in English; update
the JSON value for "footer.builtWith" to a Japanese string (e.g., "で作られています" or
another appropriate localized phrase) so it matches adjacent Japanese footer
labels, keep the key "footer.builtWith" unchanged, ensure valid JSON quoting and
comma placement, and follow the same translation style used by neighboring
entries.

In `@docs/TunGo/i18n/ru/code.json`:
- Around line 107-109: The Russian translation for peer counts uses a static
"{count} peer" string; replace the "message" value for the key
"bench.legend.peers" (and the similar entries around lines 134-136) with an ICU
plural-format string that applies Russian plural rules (one, few, many, other)
so the label correctly renders like "{count} пира/пира/пиров" depending on
count; update the JSON value to use the ICU plural syntax with the {count,
plural, one {...} few {...} many {...} other {...}} pattern so pluralization is
handled correctly by the i18n system.

---

Duplicate comments:
In `@docs/TunGo/src/components/features/styles.module.css`:
- Line 5: The Stylelint error is because CSS Modules uses the :global(...)
pseudo which selector-pseudo-class-no-unknown flags; update the Stylelint config
to whitelist the pseudo by adding ignorePseudoClasses: ["global"] under the
selector-pseudo-class-no-unknown rule so selectors like the .features
:global(.container) usages (and the other :global(...) occurrences) stop failing
lint; ensure the config change is applied to your active stylelint config file
so the rule recognizes the global pseudo across the project.

---

Nitpick comments:
In `@docs/TunGo/i18n/de/code.json`:
- Around line 167-169: The translation for the key "bench.metric.allocsNote"
currently uses the English phrase "Hot Path"; replace it with the consistent
German translation (e.g., "Kritischer Pfad") or adjust according to the
project's i18n policy to keep technical terms in English across the file,
updating the "message" value for bench.metric.allocsNote accordingly so it
matches the rest of the German translations.
- Around line 173-175: The value for the i18n key "bench.summary.egressNote"
mixes English and German; replace the message string with a fully German phrase
(e.g., "Von unbelasteten zu belasteten Sendungen") or an improved German
technical phrasing if you want to keep terms (e.g., "Von uncontended- zu
contended-Sends" avoided) so that the "bench.summary.egressNote" entry reads
clearly in German and preserves meaning.

In `@docs/TunGo/src/pages/index.module.css`:
- Around line 55-61: Stylelint is flagging the ":global(.button)" selector in
the .buttons :global(.button) rule even though :global is valid CSS Modules
syntax; update the Stylelint config to allow the pseudo-classes by adding
"global" (and "local") to the selector-pseudo-class-no-unknown ignore list so
the rule no longer reports false positives for CSS Modules selectors like
:global and :local.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e11dd380-3eb3-4479-a22e-5b97fbab689a

📥 Commits

Reviewing files that changed from the base of the PR and between cc1744f and 40794fd.

📒 Files selected for processing (15)
  • docs/TunGo/i18n/ar/code.json
  • docs/TunGo/i18n/de/code.json
  • docs/TunGo/i18n/en/code.json
  • docs/TunGo/i18n/es/code.json
  • docs/TunGo/i18n/fr/code.json
  • docs/TunGo/i18n/id/code.json
  • docs/TunGo/i18n/ja/code.json
  • docs/TunGo/i18n/pt/code.json
  • docs/TunGo/i18n/ru/code.json
  • docs/TunGo/i18n/zh-Hans/code.json
  • docs/TunGo/src/components/features/styles.module.css
  • docs/TunGo/src/css/custom.css
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/css/custom.css

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
docs/TunGo/i18n/fr/code.json (1)

107-109: Consider ICU plural forms for correct singular/plural handling.

"{count} peers" will display "1 peers" when count equals 1. If the i18n framework supports ICU MessageFormat (Docusaurus does), consider using plural rules:

"bench.legend.peers": {
  "message": "{count, plural, one {# peer} other {# peers}}"
}

This ensures grammatically correct output for both singular and plural cases.

Also applies to: 134-136

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/fr/code.json` around lines 107 - 109, The
"bench.legend.peers" message currently uses a raw "{count} peers" string which
yields "1 peers" for singular; update the message to use ICU pluralization
(e.g., "{count, plural, one {# peer} other {# peers}}") for the
"bench.legend.peers" key so singular/plural are handled correctly, and apply the
same ICU plural pattern to the other similar keys referenced in the comment (the
keys at the indicated 134-136 range) to ensure consistent grammar across
translations.
docs/TunGo/i18n/id/code.json (2)

107-108: Duplicate key pattern for peer count labels.

Both bench.legend.peers (line 108) and bench.table.peerCount (line 135) have identical messages: "{count} peer". If these are used in different contexts with the same meaning, consider consolidating to a single key to reduce maintenance overhead.

Also applies to: 134-136

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/id/code.json` around lines 107 - 108, The two i18n keys
bench.legend.peers and bench.table.peerCount both contain the identical message
"{count} peer"; consolidate them by either (A) removing one key and updating all
usages to reference a single shared key (e.g., keep bench.table.peerCount and
replace bench.legend.peers usages), or (B) if contexts differ, make the messages
distinct and use proper pluralization patterns (e.g., "{count} peer" vs "{count}
peers") and update code that calls the i18n lookup accordingly; locate
occurrences by searching for bench.legend.peers and bench.table.peerCount and
apply the rename/merge consistently.

86-97: Consider using Unicode arrow characters for consistency.

The direction labels use ASCII -> instead of the Unicode arrow . While functional, Unicode arrows provide better visual rendering across different fonts and platforms.

♻️ Suggested improvement
   "bench.direction.clientServer": {
-    "message": "Klien -> Server"
+    "message": "Klien → Server"
   },
   "bench.direction.serverClient": {
-    "message": "Server -> Klien"
+    "message": "Server → Klien"
   },
   "bench.parallel.clientServer": {
-    "message": "UDP Klien -> Server"
+    "message": "UDP Klien → Server"
   },
   "bench.parallel.serverClient": {
-    "message": "UDP Server -> Klien"
+    "message": "UDP Server → Klien"
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/i18n/id/code.json` around lines 86 - 97, Replace the ASCII arrow
"->" with the Unicode arrow "→" in the localization entries so labels render
consistently; update the JSON values for keys bench.direction.clientServer,
bench.direction.serverClient, bench.parallel.clientServer, and
bench.parallel.serverClient to use "→" (or the \u2192 escape) instead of "->".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/TunGo/i18n/ja/code.json`:
- Around line 108-109: Replace the remaining English peer labels in the Japanese
i18n bundle by localizing the strings "{count} peers" and "10k peers" (and the
other occurrences noted) into Japanese so the UI is consistent; update the JSON
values for the keys that currently contain "{count} peers" and "10k peers" (and
the duplicates at the other locations) with appropriate Japanese translations
(e.g. "{count} ピア" or "1万人のピア" or another approved locale string) ensuring the
placeholder {count} is preserved exactly.

In `@docs/TunGo/src/pages/index.module.css`:
- Line 51: Stylelint is failing on the CSS Modules pseudo-class :global used in
the selectors ".buttons :global(.button)" (both occurrences); either update
.stylelintrc.json to allow the pseudo-class by configuring
"selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["global"]
}] or add local suppression comments immediately above each selector (for
example, /* stylelint-disable-next-line selector-pseudo-class-no-unknown */) so
the rules allow :global(.button) in index.module.css; apply the chosen change to
both ".buttons :global(.button)" occurrences.

---

Nitpick comments:
In `@docs/TunGo/i18n/fr/code.json`:
- Around line 107-109: The "bench.legend.peers" message currently uses a raw
"{count} peers" string which yields "1 peers" for singular; update the message
to use ICU pluralization (e.g., "{count, plural, one {# peer} other {# peers}}")
for the "bench.legend.peers" key so singular/plural are handled correctly, and
apply the same ICU plural pattern to the other similar keys referenced in the
comment (the keys at the indicated 134-136 range) to ensure consistent grammar
across translations.

In `@docs/TunGo/i18n/id/code.json`:
- Around line 107-108: The two i18n keys bench.legend.peers and
bench.table.peerCount both contain the identical message "{count} peer";
consolidate them by either (A) removing one key and updating all usages to
reference a single shared key (e.g., keep bench.table.peerCount and replace
bench.legend.peers usages), or (B) if contexts differ, make the messages
distinct and use proper pluralization patterns (e.g., "{count} peer" vs "{count}
peers") and update code that calls the i18n lookup accordingly; locate
occurrences by searching for bench.legend.peers and bench.table.peerCount and
apply the rename/merge consistently.
- Around line 86-97: Replace the ASCII arrow "->" with the Unicode arrow "→" in
the localization entries so labels render consistently; update the JSON values
for keys bench.direction.clientServer, bench.direction.serverClient,
bench.parallel.clientServer, and bench.parallel.serverClient to use "→" (or the
\u2192 escape) instead of "->".

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dac65c59-eaec-4829-b861-9f3e10fce965

📥 Commits

Reviewing files that changed from the base of the PR and between 40794fd and de4c48f.

📒 Files selected for processing (7)
  • docs/TunGo/i18n/fr/code.json
  • docs/TunGo/i18n/id/code.json
  • docs/TunGo/i18n/ja/code.json
  • docs/TunGo/i18n/ru/code.json
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/src/pages/index.js
  • docs/TunGo/src/pages/index.module.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/TunGo/src/pages/benchmarks.module.css
  • docs/TunGo/i18n/ru/code.json

flex-wrap: wrap;
}

.buttons :global(.button) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find stylelint config files in repo
fd -HI '(^|/)\.stylelintrc(\..+)?$|stylelint\.config\.(js|cjs|mjs|json|yaml|yml)$'

# 2) Check whether config already allows :global
rg -n 'selector-pseudo-class-no-unknown|ignorePseudoClasses|global' --glob '*stylelint*'

# 3) Confirm :global selectors exist at the flagged lines
rg -n ':\s*global\(' docs/TunGo/src/pages/index.module.css

Repository: NLipatov/TunGo

Length of output: 75


🏁 Script executed:

cat -n .stylelintrc.json

Repository: NLipatov/TunGo

Length of output: 1274


🏁 Script executed:

sed -n '40,80p' docs/TunGo/src/pages/index.module.css | cat -n

Repository: NLipatov/TunGo

Length of output: 992


Stylelint will fail on :global unless rule config/suppression is added.

The .stylelintrc.json does not configure selector-pseudo-class-no-unknown to allow :global(), which is required for CSS Modules. Both .buttons :global(.button) selectors at lines 51 and 75 will trigger a linting error. Either disable the rule globally in stylelint config or add local suppression comments.

Suggested patch (local suppression)
+/* stylelint-disable-next-line selector-pseudo-class-no-unknown */
 .buttons :global(.button) {
   min-width: 0;
   padding-inline: 1.2rem;
   min-height: 2.85rem;
   font-size: 0.98rem;
   justify-content: center;
 }

 `@media` screen and (max-width: 996px) {
@@
+  /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
   .buttons :global(.button) {
     width: 100%;
     min-height: 2.7rem;
     font-size: 0.95rem;
   }
 }

Also applies to: 75-75

🧰 Tools
🪛 Stylelint (17.4.0)

[error] 51-51: Unexpected unknown pseudo-class selector ":global" (selector-pseudo-class-no-unknown)

(selector-pseudo-class-no-unknown)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/TunGo/src/pages/index.module.css` at line 51, Stylelint is failing on
the CSS Modules pseudo-class :global used in the selectors ".buttons
:global(.button)" (both occurrences); either update .stylelintrc.json to allow
the pseudo-class by configuring "selector-pseudo-class-no-unknown": [true, {
"ignorePseudoClasses": ["global"] }] or add local suppression comments
immediately above each selector (for example, /* stylelint-disable-next-line
selector-pseudo-class-no-unknown */) so the rules allow :global(.button) in
index.module.css; apply the chosen change to both ".buttons :global(.button)"
occurrences.

@NLipatov NLipatov merged commit a8ab54c into main Mar 16, 2026
10 checks passed
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.

1 participant