Devolutions Gateway is a relay server. The project is a polyglot monorepo containing:
- Rust workspace: gateway service, agent service, jetsocat CLI tool, and dedicated testsuite
- TypeScript/Angular pnpm workspace: web UI with multiple packages and apps
- C# desktop agent: Windows-specific agent implementation
- PowerShell module: management and configuration tools
cargo +nightly fmt --all
cargo clippy --workspace --tests -- -D warnings
cargo test --workspace- Pedantic Clippy lints are enabled; THINK before suppressing.
- Use
#[expect(clippy::<lint_name>, reason = "<explain why>")]with clear reasoning. - Tests go in
testsuite/tests/, helpers intestsuite/src/. - Consider
proptestfor property-based testing,rstestfor parameterized tests.
pnpm install
pnpm fmt:write
pnpm lint
pnpm testpowershell/build.ps1
powershell/run-tests.ps1Follow standard .NET conventions.
Use one of these formats:
- Jira ticket:
DGW-338(ticket ID as branch name) with optional description (e.g.:DGW-338-websocket-compression-support) - GitHub issue: Follow standard format (e.g.,
fix/123-description)
Format: <type>(<scope>): <description>
Scopes (what appears in CHANGELOG.md):
dgw- Devolutions Gateway serviceagent- Devolutions Agent service and artifactsjetsocat- Jetsocat CLI toolwebapp- Devolutions Gateway standalone frontend ONLY
Library scopes (excluded from changelog):
dotnet-*- .NET libraries (e.g.,dotnet-utils)ts-*- TypeScript libraries (e.g.,ts-client)*deps*,*openapi*,*npm*- Dependency updates
Types:
feat:New featurefix:Bug fixdocs:Documentation onlystyle:Code style (formatting, semicolons, etc)refactor:Code restructuring without behavior changeperf:Performance improvementstest:Adding missing testsbuild:Build system or dependenciesci:CI configurationchore:Maintenance tasks
- User-oriented description (what users gain/notice)
- Can include technical context for developers
- Avoid internal implementation details
- Focus on impact and benefits
- This text appears in the changelog for feat/fix/perf
Always include issue reference:
Issue: DGW-123 (Jira ticket)
Issue: #456 (GitHub issue)
Add a separate comment after PR creation with:
- Technical implementation details
- Design decisions and trade-offs
- Testing approach
- Breaking changes or migration notes
- Any context helpful for reviewers
Title: feat(dgw): add WebSocket compression support
Body:
Adds support for per-message deflate compression on WebSocket connections,
reducing bandwidth usage by up to 70% for typical JSON payloads. This
significantly improves performance for users on limited bandwidth connections.
Issue: DGW-338
Then add comment:
Implementation notes:
- Uses permessage-deflate extension (RFC 7692)
- Configurable compression level (1-9, default: 6)
- Memory pool for deflate contexts to avoid allocations
- Benchmarks show 15% CPU increase for 70% bandwidth reduction
Title: fix(ts-client): handle reconnection timeout properly
Body:
Fixes an issue where the TypeScript client library would not properly
handle reconnection timeouts, causing infinite connection attempts.
Issue: DGW-422
Follow the IronRDP style guide. These guidelines summarize the key points for this project.
-
Return types: Use
crate_name::Result(e.g.,anyhow::Result), not bareResult. Exception: when type alias is clear (e.g.,ConnectionResult). -
Error messages: lowercase, no punctuation, one sentence.
- ✅
"invalid X.509 certificate" - ❌
"Invalid X.509 certificate."
- ✅
-
Log messages: Capital first letter, no period.
- ✅
info!("Connect to RDP host"); - ❌
info!("connect to RDP host.");
- ✅
-
Use structured fields:
info!(%server_addr, "Looked up server address"); -
Name fields consistently: use
errornotefor errors.
-
Inline comments: Full sentences with capital and period.
- ✅
// Install a very strict rule to ensure tests are limited. - ❌
// make sure tests can't do just anything - Exception: brief tags (
// VER,// RSV) don't need periods.
- ✅
-
Size calculations: Comment each field
const FIXED_PART_SIZE: usize = 1 /* Version */ + 1 /* Endianness */ + 2 /* CommonHeaderLength */ + 4 /* Filler */;
-
Invariants:
- Define with
// INVARIANT: … - Loop invariants: before the loop
- Field invariants: in doc comments
- Function output invariants: in function doc comments
- When referencing in
#[expect(...)]: don't useINVARIANT:prefix
- Define with
-
Markdown: For prose paragraphs, use one sentence per line in
.mdfiles.
Follow Angular style guide for components.
Follow standard PowerShell conventions.
- Main README:
README.md - Changelog:
CHANGELOG.md - Style guide:
STYLE.md - Web app:
webapp/README.md - Configuration:
config_schema.json - Cookbook:
docs/COOKBOOK.md