Contributions are what make the open-source community such an amazing place to learn, inspire, and create.
Thank you for your interest in contributing to the LFX V2 Voting Service! This document provides guidelines and instructions for contributing to the project.
- Code of Conduct
- Getting Started
- Development Setup
- Getting Dev Credentials
- License Headers
- Code Style
- Architecture Guidelines
- Commit Messages
- Pull Request Process
- Testing
By participating in this project, you agree to abide by the Linux Foundation Code of Conduct.
- Fork the repository
- Clone your fork locally
- Create a new branch for your feature or bug fix
- Make your changes
- Push your changes to your fork
- Submit a pull request
See README.md — Getting Started for full setup instructions: prerequisites, installation, environment variables, running locally, and optional NATS + Heimdall infrastructure via the lfx-platform Helm chart.
The service requires ITX OAuth2 credentials (ITX_CLIENT_ID and ITX_CLIENT_PRIVATE_KEY). Find them in:
1Password → Linux Foundation org → LFX V2 vault → LFX V2 Voting Service Env Vars (secure note)
- The private key is an RSA key in PEM format
- Store the key locally at
tmp/local.private.key(gitignored) and reference it with$(cat tmp/local.private.key)
For local development, you can bypass NATS and JWT auth entirely using the flags shown in the Quick Start above. The only credential you truly need to make proxy calls to the ITX dev environment is ITX_CLIENT_ID and ITX_CLIENT_PRIVATE_KEY.
IMPORTANT: All source code files must include the appropriate license header. This is enforced by our CI/CD pipeline.
The license header must appear at the top of every source file and must contain:
Copyright The Linux Foundation and each contributor to LFX.
SPDX-License-Identifier: MIT
// Copyright The Linux Foundation and each contributor to LFX.
// SPDX-License-Identifier: MIT
package yourpackage# Copyright The Linux Foundation and each contributor to LFX.
# SPDX-License-Identifier: MIT# Copyright The Linux Foundation and each contributor to LFX.
# SPDX-License-Identifier: MIT- CI Pipeline: GitHub Actions verifies all files have proper headers on every pull request (excludes
gen/*andcmd/voting-api/kodata/*)
- Follow Effective Go
- Use
gofmt/goimportsfor formatting — runmake fmtbefore committing - All exported functions and types must have doc comments
- Domain errors use the
ErrorTypeenum pattern (seeinternal/domain/) - Use structured logging (
slog) — neverfmt.Printlnorlog.Printf
The project uses golangci-lint. Run linting before committing:
# Run linter
make lint
# Check formatting + lint without modifying files
make checkThe linter config is in revive.toml and .golangci.yml.
This service uses clean architecture with clear layer boundaries. Understand them before making changes:
api/voting/v1/design/— Goa DSL only; no business logicinternal/domain/— interfaces and domain models; no external dependenciesinternal/service/— business logic; depends only on domain interfacesinternal/infrastructure/— external integrations (ITX proxy, NATS, auth)cmd/voting-api/— wiring, converters, and Goa interface implementation
Dependencies flow inward. Infrastructure depends on domain, not the other way around.
Follow the checklist in the README's Adding New Endpoints section — it covers the full Goa → service → proxy chain.
When something doesn't work, fix the root cause. Disabling auth, bypassing linting with //nolint without explanation, or adding build hacks are not fixes. TODO: TEMPORARY bypasses have a tendency to reach production.
Changes that affect the entire application — middleware, NATS consumer configuration, new infrastructure integrations — are architectural decisions. They need standalone PRs with focused review, not bundled inside feature work.
Follow the conventional commit format:
type(scope): subject
body
footer
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
feat(votes): add bulk resend endpoint
Implements POST /api/v1/votes/{vote_uid}/bulk_resend to proxy the
ITX bulk email resend call.
Closes #42
All commits must be signed off per the Developer Certificate of Origin:
git commit --signoffThis adds a Signed-off-by line to your commit message.
Use the format <type>/<ticket-or-description>, for example:
feat/LFXV2-123-add-bulk-resendfix/LFXV2-456-fix-id-mappingchore/update-dependencies
- Keep PRs focused on a single concern — a feature PR should contain only the feature
- Architectural decisions require their own PR — changes to middleware, infrastructure wiring, or NATS configuration need standalone discussion and approval
- Never mix security changes with feature work — auth middleware modifications must be reviewed independently
- Update Documentation: Update README or docs/ for any new features or configuration changes
- Add Tests: Include unit tests for new functionality
- Pass All Checks: Ensure
make checkandmake testpass locally - License Headers: Verify all new files have the correct license header
- API Generation: If you modified Goa design files, run
make apigenand commit the regenerated files - Clear Description: Provide a clear description of changes and link any related issues or Jira tickets
Use the same conventional commit format for PR titles:
feat(votes): add bulk resend endpoint
# Run all tests
make test- All new features must include unit tests
- Tests must pass with
-raceflag (already enforced bymake test) - Mock external dependencies — tests should not require a live ITX or NATS connection
If you have questions about contributing, please:
- Check existing issues and discussions on GitHub
- Open a new issue for clarification
- Contact the LFX team at support@linuxfoundation.org
Thank you for contributing to LFX V2 Voting Service!