Thank you for your interest in contributing to Surgewave!
Before we can accept your contribution, you must sign our Contributor License Agreement (CLA). This protects both you and the project.
What this means:
- Your contributions will be licensed under the same Apache License 2.0 as the rest of the Surgewave core
- You retain copyright of your contributions
- You grant Küstenlogik the right to relicense your contribution in our premium-tier repositories (e.g. Surgewave.Ai, Surgewave.Governance) under the Business Source License 1.1 — this lets us keep building the commercial extensions that fund Surgewave development
How it works:
- Open a Pull Request
- The CLA Assistant bot will comment asking you to sign
- Click the link and sign the CLA (one-time, covers all future contributions)
- Once signed, the bot marks the PR as ready for review
If you have questions about the CLA, contact: licensing@kuestenlogik.com
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR-USERNAME/Surgewave.git - Create a branch:
git checkout -b feature/my-feature - Install .NET 10 SDK
- Build:
dotnet build Kuestenlogik.Surgewave.slnx - Test:
dotnet test Kuestenlogik.Surgewave.slnx
feature/description— New featuresfix/description— Bug fixesdocs/description— Documentationrefactor/description— Code improvements
Follow conventional commits:
feat: add new featurefix: resolve bugdocs: update documentationrefactor: improve code structuretest: add testschore: maintenance tasks
- Sign the CLA (first-time only)
- Ensure all tests pass:
dotnet test Kuestenlogik.Surgewave.slnx - Ensure zero build warnings:
dotnet build Kuestenlogik.Surgewave.slnx -c Release - Add tests for new features
- Update documentation if needed
- Update ROADMAP.md if implementing a roadmap item
- Follow existing patterns in the codebase
- One class/interface per file, named by content
- Use
<summary>XML docs on all public members - Feature toggles:
Surgewave:FeatureName:Enabled(default false) - DI pattern:
AddSurgewaveXxx()/MapSurgewaveXxx()
- Unit tests with xUnit v3
- Integration tests in
tests/Kuestenlogik.Surgewave.IntegrationTests/ - NSubstitute for mocking
- Test naming:
MethodName_Scenario_ExpectedResult
./scripts/run-coverage.ps1Surgewave has a plugin system for extending the broker. See the Plugin Development Guide for creating your own plugins.
- Create a .NET 10 class library
- Reference
Kuestenlogik.Surgewave.Plugins - Implement a plugin interface (
IBrokerPlugin,IProtocolPlugin,IStorageEnginePlugin,ISourceNode,ISinkNode, etc.) - Create
plugin.jsonmanifest in the project root (see Plugin manifest below) - Optionally create
pluginsettings.jsonnext to it for your recommended config defaults - Pack:
dotnet publish -c Release -p:SurgewavePackPlugin=true(orsurgewave plugins pack --project .) - Install:
surgewave plugins install <plugin-id>-<version>.swpkg - Inspect:
surgewave plugins show <plugin-id>andsurgewave config view appsettings.json --explain
Every Surgewave plugin needs a plugin.json next to its source files. Minimal shape:
{
"id": "my-org.my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "What this plugin does",
"assemblies": [ "MyOrg.MyPlugin.dll" ],
"tags": [ "category", "subcategory" ],
"pluginSettings": "pluginsettings.json"
}The pluginSettings field is optional (defaults to pluginsettings.json if a
file with that name exists next to the manifest). It tells the packager which
file to bundle as the plugin's default-config payload — any plain filename is
accepted (e.g. mqtt-defaults.json), but stick with pluginsettings.json
unless you have a strong reason.
A plugin can ship recommended configuration defaults that the broker layers
beneath the user's appsettings.json. Three tiers, lowest precedence first:
tier 1 — pluginsettings.json from plugins/<id>/ ← plugin author
tier 2 — broker appsettings.json + appsettings.{Env}.json
tier 3 — environment variables + command-line args
User values always win, but plugin defaults take effect immediately after
surgewave plugins install — no manual config editing required. Example: an MQTT
plugin can ship recommended Port, MaxClients and TopicPrefix values; the
operator only needs to set Enabled: true to start the adapter.
For configuration POCOs, implement IValidatableConfig and add a public
SectionName constant so surgewave config validate can find the type via
reflection:
public sealed class MyPluginConfig : IValidatableConfig
{
public const string SectionName = "Surgewave:MyPlugin";
[Range(1, 65535)]
public int Port { get; set; } = 8080;
public IReadOnlyList<string> Validate() => ConfigValidator.ValidateDataAnnotations(this);
}# Pack and install in one go
dotnet publish -c Release -p:SurgewavePackPlugin=true
surgewave plugins install artifacts/pub/packages/my-plugin-1.0.0.swpkg --force
# Inspect what was installed (manifest, assemblies, bundled defaults)
surgewave plugins show my-org.my-plugin
# Verify your plugin's config defaults merge correctly with the broker's appsettings
surgewave config view path/to/broker/appsettings.json --explain
# Validate the merged effective config
surgewave config validate path/to/broker/appsettings.jsonsrc/ — Source code
tests/ — Test projects
benchmarks/ — Performance benchmarks
docs/ — Documentation (DocFX)
deployments/ — Docker, Helm, K8s, installer, monitoring
scripts/ — Build/test scripts
By contributing to Surgewave, you agree that your contributions will be licensed under the Apache License 2.0 and may be relicensed by Küstenlogik in premium-tier repositories under the Business Source License 1.1 (see the CLA section above).
- Open a GitHub Issue
- Check the documentation