Contributing¶
Contributions to Bor are welcome: bug reports, fixes, new policy types, tests and documentation. This page describes how to submit a change, what reviewers look for, and the coding and compliance rules every change has to follow.
Ways to contribute¶
- GitHub pull requests against VuteTech/Bor (preferred).
- Patches by email to bor@vute.tech, if you prefer not to use GitHub.
- Issues in the GitHub issue tracker
for bugs and feature requests. For a bug, include steps to reproduce,
expected and actual behavior, the distribution and the server and agent
versions, and relevant log output (
journalctl -u bor-agent,journalctl -u bor-server). For a feature request, describe the use case before proposing a solution.
Security problems are reported privately; see Reporting security vulnerabilities.
Contributions made with the help of AI coding assistants are welcome under the rules in AI-assisted contributions: you must understand and test everything you submit, and disclose tool use in the pull request.
Pull request workflow¶
Bor uses the fork and branch workflow against master.
-
Fork the repository on GitHub and clone your fork:
-
Create a feature branch from the current
master: -
Make the change, with tests, following the conventions below.
-
Verify locally (see Testing and linting):
-
Commit with a Conventional Commits message, push to your fork and open a pull request against
VuteTech/Bor:master. -
In the pull request description, explain what problem the change solves, how you tested it, any breaking changes or migration notes, and reference related issues (
Closes #42).
Keep each pull request to a single concern. Split unrelated changes into separate pull requests. Reviewers may ask you to rebase, squash or split a pull request before it is merged.
Email patches¶
Format patches with git format-patch, with a cover letter for a series:
Use the same commit message conventions, and add a sign-off line
(git commit --signoff) to confirm that you have the right to submit the
change under the project license.
Commit messages¶
Commits follow the Conventional Commits specification:
<type>(<scope>): <short summary>
[optional body: explain why, not only what]
[optional footer, e.g. Closes #42]
- Types
feat,fix,docs,style,refactor,test,chore,perf- Scopes
server,agent,frontend,proto,packaging,ci,docs. A narrower scope that names the feature (for exampleauth) is also used in the history.
Write the summary in the imperative mood ("add", "fix", not "added") and keep it under 72 characters. Examples:
feat(agent): add KDE Plasma desktop notification on policy update
fix(server): correct node_count query after junction table migration
docs: add development environment guide
test(server): add table-driven tests for policy binding service
chore(packaging): add nfpm configs for deb/rpm/apk/arch packages
Code review¶
Reviewers look at:
- Correctness and tests. New behavior and bug fixes come with tests; all CI jobs pass.
- Conventions.
gofmt, golangci-lint with 0 issues,npm run typecheckfor UI changes, and the rules on this page. - Security. Changes to authentication, authorization, the PKI, enrollment and policy enforcement get extra scrutiny. Expect questions about failure modes and input validation.
- Scope. One concern per pull request, no unrelated reformatting.
- Completeness. Database changes include a migration, protobuf changes include the regenerated code, file-based policy types are wired into the agent's file watcher (see Adding a policy type), and user-visible changes update the documentation.
Maintainers may close pull requests that are abandoned or out of scope.
Coding conventions¶
Go¶
- Follow standard Go project layout and Effective Go.
- Wrap errors with context:
fmt.Errorf("failed to load policy %s: %w", id, err). Do not swallow errors silently. - Pass
context.Contextas the first argument to functions that do I/O or can be cancelled. Avoid global state; pass dependencies explicitly. - Prefer the standard library and existing dependencies. Discuss a significant new dependency in an issue first.
- Exported identifiers have godoc comments.
- Write table-driven tests.
gRPC¶
- Return proper status codes from
google.golang.org/grpc/statusandcodes(for examplecodes.InvalidArgument,codes.PermissionDenied,codes.NotFound), not generic errors. - Clients use timeouts and retries; the agent reconnects with capped exponential backoff.
Database¶
- Every schema change is a new pair of migration files in
server/internal/database/migrations/(NNNNNN_name.up.sqland.down.sql). Never edit a migration that has been released. - Use parameterized queries (placeholders), never string concatenation.
- Wrap multi-step operations in a transaction.
Frontend¶
- PatternFly 6, React function components with hooks, explicit TypeScript
types (avoid
any). - Use the shared components and design tokens described in
Frontend before writing new ones. Colors come from
--pf-t--*tokens, never raw hex. - Keep WCAG 2.2 Level AA: labels on icon-only buttons,
aria-labelon spinners, live regions for status messages, no color-only information, visible focus rings.
Text style¶
These rules apply to every file in the repository: code, comments, strings, documentation and commit messages.
- Do not use the Unicode right arrow or the em and en dash characters. Write
->for arrows and a plain-for dashes and ranges. - Development-time planning and working documents stay out of the repository. Never reference them (by path or section) from code, comments, documentation or commit messages.
Security and compliance rules¶
Bor targets FIPS 140-3, BSI TR-02102, SOG-IS, eIDAS, NIS2, the EU Cybersecurity Act and GDPR. Do not introduce dependencies, algorithms or patterns that would break these targets. In practice:
| Area | Rule |
|---|---|
| TLS | Minimum TLS 1.2, prefer 1.3. AEAD cipher suites only (AES-GCM, ChaCha20-Poly1305). No CBC suites |
| Hashing | SHA-256 or SHA-512. No MD5, no SHA-1 (except where a legacy protocol requires it, opt-in and logged) |
| Keys | RSA 3072 bits or more, ECDSA P-256 or P-384, Ed25519. AES-256 preferred, AES-128 minimum |
| Algorithms | Only FIPS-approved primitives from the Go standard library crypto packages. No RC4, Blowfish, 3DES, non-NIST curves or custom crypto |
| Passwords | bcrypt with cost 12 or more, or Argon2id. Never store plaintext or reversible passwords |
| Tokens | Every JWT has an expiry; HMAC-SHA256 at minimum |
| Audit | Authentication events, privilege changes and policy changes are logged with timestamp, actor, action and target |
| Secrets in logs | Never log passwords, TOTP secrets, private keys, enrollment tokens or recovery keys. Redact before storage |
| Personal data | Collect only what is needed; audit data with personal data must respect retention and erasure settings |
| Input | Validate input at every boundary (REST, gRPC, files read by the agent) |
The full cryptographic inventory and standards mapping are in Security and compliance.
Reporting security vulnerabilities¶
Do not open a public issue for a security vulnerability. Report it privately to bor@vute.tech with:
- a description of the vulnerability and its impact,
- steps to reproduce or a proof of concept,
- any mitigations you know of.
The project acknowledges reports within 48 hours and aims to ship a fix within 90 days of the initial report, coordinating disclosure with the reporter.
License¶
Bor is licensed under the GNU Lesser General Public License v3.0 or later
(LGPL-3.0-or-later, see LICENSE.md). By contributing, you agree that your
contribution is licensed under the same terms.
Go, TypeScript and JavaScript source files start with an SPDX license header:
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright (C) 2026 Vute Tech LTD
// Copyright (C) 2026 Bor contributors
Add this header to every new Go, TypeScript and JavaScript file.