Thank you for your interest in contributing to redb.Tsak — the runtime container for redb.Route.
Before contributing, please read the redb.Route CONTRIBUTING guide.
The conventions there (coding style, PR process, commit messages) apply here as well.
- Reporting Bugs
- Feature Requests
- Development Setup
- Code Guidelines
- Adding a New CLI Command
- Adding a New REST Endpoint
- Module Development
- Testing
- Commit Format
When filing an issue include:
- Project: which sub-project (
Worker,CLI,Web,Client,Core,Cluster, etc.) - Version:
tsak --versionor the NuGet package version - Deployment mode:
InMemory/Redb:Postgres/Redb:MSSql/ Cluster - .NET version:
dotnet --version - Minimal reproduction:
- Relevant
appsettings.jsonexcerpt (no credentials — see DEPLOYMENT_SECRETS.md) - The
tsakCLI command or REST call that triggers the bug - The module code (stripped down) if module loading is involved
- Relevant
- Expected behavior
- Actual behavior — include structured log output from
tsak logsor the worker console
Before opening a feature request:
- Check whether the feature belongs in redb.Tsak (runtime container infrastructure) or in redb.Route (pipeline DSL and transports). Tsak does not implement connectors or EIP processors.
- Search existing issues for duplicates.
- Open an issue with:
- Problem statement — what you cannot do today
- Proposed solution — API shape, config keys, CLI commands
- Alternatives considered
- Whether this requires a breaking change to any public interface
# Clone
git clone https://github.com/redbase-app/redb.git
cd redb
# Restore
dotnet restore redb.Tsak
# Build Worker
dotnet build redb.Tsak/src/redb.Tsak.Worker
# Run Worker (standalone, no DB)
dotnet run --project redb.Tsak/src/redb.Tsak.Worker
# Run CLI
dotnet run --project redb.Tsak/src/redb.Tsak.CLI -- help
# Run Web dashboard
dotnet run --project redb.Tsak/src/redb.Tsak.WebFor cluster mode, start PostgreSQL and set:
{
"ConnectionStrings": { "Postgres": "..." },
"Tsak": {
"Storage": { "Type": "Redb" },
"Redb": { "Provider": "postgres" },
"Cluster": { "Enabled": true }
}
}All guidelines from the redb.Route CONTRIBUTING guide apply. Tsak-specific additions:
- No business logic in the Worker project —
redb.Tsak.Workeris only DI wiring, configuration binding, and hosted service registration. Business logic lives inredb.Tsak.Core. _systemcontext is sacred — never let API endpoints stop, delete, or modify the_systemcontext. Its protection logic lives inContextManagerand must not be weakened.- Constant-time comparisons for keys — any code that compares API key hashes must use
CryptographicOperations.FixedTimeEquals. Do not use==orstring.Equalsfor secrets. - No distributed state without epoch fencing — cluster operations that mutate shared state must carry an epoch token to prevent split-brain on network partition recovery.
- Config changes must preserve 5-layer semantics — if you add a new config key, define it in the
defaultcontext and document which layers can override it. - All new endpoints need auth checks — use the
[RequireRole("...")]attribute or the equivalent middleware. No anonymous write endpoints. - Ring buffer log — use structured Serilog logging, not
Console.WriteLine. TheLogRingBuffersink must capture all operational events.
- Create a command file in
redb.Tsak.CLI/Commands/. - Subclass
TsakCommand(or the appropriate group base). - Register the command in
Program.csunder the correct group. - Add table rendering via
Spectre.Console— match the visual style of existing commands. - Add
--output jsonsupport using the sharedOutputFormatter. - Write tests in
redb.Tsak.CLI.Tests/— cover success path, error responses, and auth failure. - Update
README.mdcommand list.
Command implementation checklist:
- Handles
--server/--keyglobal options for targeting a remote Tsak instance - Propagates
CancellationTokenthrough all async calls - Returns appropriate exit codes (0 = success, 1 = error, 2 = auth failure)
- Produces machine-readable JSON when
--output jsonis passed - Includes a
--helpdescription
- Identify which controller the endpoint belongs to (or create a new one if the category is new).
- Add the corresponding method to
ITsakApiClientand implement it inTsakApiClient. - Add a DTO to
redb.Tsak.Contractsif new request/response shapes are needed. - Annotate with the appropriate
[RequireRole(...)]attribute. - Document the endpoint in
README.md— update the endpoint count in the table. - Add unit tests for the service layer and integration coverage for the controller method.
A Tsak module is a plain .NET class library. To contribute module examples:
- Follow the
InitRoute.main(IRouteContext)entry point convention. - Ship
manifest.json,context.json, and{Module}.config.jsonalongside the DLL. - Do not assume a specific DB or infrastructure — use
context.jsonfor defaults so operators can override via Layer 5. - Document the module's routes, transports, and config keys in its own
README.md. - See redb.Route.Demo as a reference implementation.
Run the full test suite:
dotnet test redb.Tsak/tests/redb.Tsak.Tests
dotnet test redb.Tsak/tests/redb.Tsak.CLI.TestsTesting requirements for PRs:
- New services must have unit tests using
NSubstitutefor dependencies andFluentAssertionsfor assertions. - Cluster logic must be tested with mocked
IClusterCoordinator— do not write tests that require actual distributed locking. - CLI commands must have tests covering at least the success path and authentication failure.
- Hot-reload logic must have tests that simulate file-change events without touching the file system (use the
IFileSystemWatcherabstraction). - All tests must pass without environment variables, database connections, or network access.
<type>(<scope>): <short description>
[optional body]
[optional footer]
Types: feat, fix, docs, refactor, test, chore
Scopes: core, worker, cli, web, client, contracts, cluster, hotreload, security, scheduler, monitoring, watchdog
Examples:
feat(cluster): add weighted assignment strategy
Adds a WeightedRoundRobin assignment manager that distributes contexts
based on node metric scores (CPU + memory composite).
Closes #142
fix(security): use constant-time comparison in InMemory key store
The InMemory store was using string.Equals which is susceptible to
timing attacks. Replaced with CryptographicOperations.FixedTimeEquals.
feat(cli): add `route stop` and `route start` commands