The repository has carried only a LICENSE and a README, which scores 42% on GitHub's community profile against ihasmail's 85% and, more to the point, leaves someone who finds a vulnerability with nowhere to send it but a public issue. SECURITY.md is the one that matters. It names cross-tenant data exposure as the highest-severity class, since that is the guarantee this project actually sells and the one hardest to be sure of. It also puts the two knowingly unverified areas in front of a reporter -- Phase 4 beyond its audit-logging guarantees, and the Windows agent, which has never run on Windows -- so a finding there is not mistaken for a regression in a path that was ever verified. And it declares the demo credential out of scope explicitly: it is published on purpose, prefilled on the login page and baked into the web bundle, so a report about it costs everyone time. CONTRIBUTING.md is written for this tree rather than adapted loosely from the other one: the storage/query split, PostgreSQL being control-plane only, the enterprise/ module boundary core never imports across, and the fact that the whole repository is AGPLv3 with no feature gate. Setup is the compose path from the README, including COMPOSE_PROFILES, so the two cannot drift into disagreeing. CODE_OF_CONDUCT.md is Contributor Covenant 2.0, copied from ihasmail with one fix: that copy never filled in the contact placeholder, so its reporting sentence ends at "responsible for enforcement at ." -- a code of conduct with no way to report anything. Worth fixing there too. Signed-off-by: John Coffey <[email protected]>
6.7 KiB
Contributing to Cairn OBS
Thanks for your interest in contributing to Cairn OBS — open-core, Kubernetes-native log aggregation and observability. Contributions of all kinds are welcome: bug reports, feature requests, code, documentation, and testing.
Code of Conduct
By participating in this project you agree to abide by the Code of Conduct. Be constructive, be patient with newcomers, and keep discussion focused on the project.
Before You Start
- Read
docs/architecture.mdbefore changing any component. The storage/query split in particular is deliberate: ClickHouse serves analytics, Tantivy serves full-text, and one query language compiles to a single plan across both. Changes that blur that line need discussion first. - PostgreSQL is control-plane only — dashboards, panels, alert rules and state, notification targets, delivery log. Log data never touches it. That boundary is about transactional read-modify-write, not preference.
enterprise/is a separate Go module that core never imports from. Since the Phase 6 relicensing that boundary is architectural rather than legal — it keeps core buildable and deployable standalone, and keeps tenant resolution server-side. Please don't reach across it.- The whole repository is AGPLv3,
enterprise/included. There is no feature gate and no paid tier holding code back. Anything you contribute is distributed under AGPL-3.0, including for hosted/SaaS deployments.
How to Contribute
Reporting Bugs
Search existing issues first. When filing a bug, include:
- A clear, descriptive title
- Steps to reproduce, and expected vs. actual behaviour
- Which component —
agent,ingest,api,search,alerting,enterprise,web,cli,deploy - How you're running it:
docker compose, the Helm chart, or something else, and whichCOMPOSE_PROFILESif compose - Relevant logs from the component, and the query if the bug is in query behaviour
- Whether it reproduces from a clean
docker compose down -v && docker compose up
Two areas are known to be unverified rather than broken — Phase 4 (RBAC and tenant isolation) beyond its audit-logging guarantees, and the Windows agent, which has never run on real Windows. Both are called out in the README. Reports against them are welcome; please say that's what you were testing.
Suggesting Features
Open an issue describing:
- The problem you're trying to solve, not just the solution
- Where it sits relative to the architecture — which component owns it, and whether it crosses the storage/query split or the
enterprise/boundary - Roughly what it costs at volume, if it touches the ingest or query path. Cost-per-GB is a design goal, not an afterthought.
For larger changes, open an issue to discuss the approach before submitting a pull request — this saves everyone time if the direction needs adjusting.
Submitting Pull Requests
- Fork the repository and create your branch from
main. - Name your branch descriptively, e.g.
fix/tantivy-merge-stallorfeat/alert-absence-rules. - Keep PRs focused — one logical change per PR.
- Write clear commit messages describing what changed and why. The "why" matters more than the "what"; the diff already says what.
- Add or update tests in the component you touched. Each top-level directory carries its own unit tests.
- Update documentation if your change affects setup, configuration, the query language, or user-facing behaviour.
- Open the pull request against
main, with a summary, any related issue numbers, screenshots for UI changes, and what you actually ran to check it.
Please sign off your commits: git commit -s adds the Signed-off-by trailer, which is a statement that you have the right to submit the work under this project's licence. GitHub enforces it for commits made through the web interface; for everything else it is asked for rather than blocked.
CI
Three workflows run on a pull request:
- License compliance — the dependency licence inventory under
docs/compliance/must stay accurate. A new dependency with an incompatible licence fails the build. - Security scan
- Web route check — the route lists are kept honest against the actual SvelteKit routes, so an unrouted path answers 404 rather than rendering something.
Code Style
- Match the existing formatting and naming conventions in the component you're editing. It's a polyglot tree: Rust in
agentandsearch, Go iningest,api,alerting,enterpriseandcli, TypeScript and Svelte inweb. cargo fmtandgofmtoutput is the standard; don't hand-format around them.- Prefer clarity over cleverness. This is infrastructure people page on.
- Comment the non-obvious, especially anything about query planning, tenant scoping, or the exactly-once/at-least-once properties of the ingest path — those are easy to get subtly wrong and expensive to debug later.
Development Setup
- Clone your fork:
git clone https://github.com/YOUR-USERNAME/cairnobs.git cd cairnobs - Bring the stack up:
The web UI is on http://localhost:3000 and the API on
docker compose up:8080; alerting is on:8081and enterprise auth on:8082. The agent connects to ingest over mTLS gRPC on:4317.searchpublishes no host port — it's reachable only on the compose network. COMPOSE_PROFILESin.envselects the query-serving binary:single-tenant(default) orenterprisefor the multi-tenant path. They're mutually exclusive, the same choice Helm'senterprise.enabledflag makes for a real cluster. Override per invocation withCOMPOSE_PROFILES=enterprise docker compose up.- Exercise the path you changed end to end — for ingest or query work that means getting a real log line in and querying it back, not just a passing unit test.
Review Process
- A maintainer will review your PR and may request changes.
- Please respond to review feedback in a timely manner; PRs with no activity for an extended period may be closed, and can be reopened once updated.
- Once approved, a maintainer will merge the PR.
Reporting Security Issues
Please do not open a public issue for security vulnerabilities. See SECURITY.md for how to report privately, and for what is in and out of scope — cross-tenant data exposure is the class we most want to hear about.
Questions?
If you're unsure whether something is a good fit, open an issue and ask, or start a discussion. Discussion before you invest time in a PR is welcome.
Thanks again for helping improve Cairn OBS.