Skip to main content
Version: 2.0.0

Contribution Guidelines

Thank you for your interest in contributing to the Pyx Identity Resolver! This guide covers the conventions and workflows you should follow when contributing to the project.

Semantic line breaks

This project uses Semantic Line Breaks in all documentation and Markdown files. Rather than wrapping lines at a fixed column width, you break lines at natural language boundaries -- typically after sentences, clauses, or logical phrases.

Why? Semantic line breaks make diffs cleaner and easier to review. When you change a single sentence, only that line shows up in the diff rather than a reflowed paragraph.

For example:

<!-- Good: semantic line breaks -->
The application uses MinIO for object storage.
Each identifier scheme is stored as a separate object,
and link sets are built from active responses only.

<!-- Avoid: long unbroken lines -->
The application uses MinIO for object storage. Each identifier scheme is stored as a separate object, and link sets are built from active responses only.

Branching strategy

Branch naming

Use the following prefixes for your branches:

PrefixPurposeExample
feature/New features or enhancementsfeature/link-management-crud
fix/Bug fixesfix/linkset-content-type
hotfix/Critical production fixeshotfix/1.2.1
release/Release preparationrelease/1.2.0
docs/Documentation-only changesdocs/contributing-guide
refactor/Code refactoringrefactor/storage-adapter
test/Test additions or improvementstest/e2e-link-resolution
chore/Maintenance taskschore/upgrade-nestjs
infra/Infrastructure or CI changesinfra/package-pipeline

Pull request workflow

  1. Create your branch from master.
  2. Make your changes, committing in logical chunks.
  3. Push your branch and open a pull request against master.
  4. Ensure all CI checks pass (tests, lint, format, docs build).
  5. Request a review from a team member.
  6. Address any feedback, then merge once approved.

PR title format

Pull request titles are validated by the Lint Commit Messages workflow using amannn/action-semantic-pull-request and must follow the Conventional Commits format:

type(scope): description

Allowed types:

TypePurpose
featA new feature
fixA bug fix
docsDocumentation only
styleFormatting, missing semicolons, etc. (no logic change)
refactorCode restructuring without changing behaviour
perfPerformance improvements
testAdding or updating tests
buildBuild system or dependency changes
ciCI/CD configuration changes
choreMaintenance tasks
revertReverting a previous commit

Examples:

feat(link-registration): add link management CRUD endpoints
fix(link-resolution): correct content type for linkset response
docs: update contributing guide
test(identifier-management): add edge case coverage for validation

Code style and conventions

Language and framework

The application is built with NestJS (a Node.js framework) using TypeScript. Tests use Jest.

Formatting and linting

The project uses Prettier for formatting and ESLint for linting. A lint-staged configuration runs both tools on staged files via a Husky pre-commit hook.

Before pushing, you can run these checks manually:

cd app

# Check formatting
npm run format:check

# Auto-format files
npm run format

# Check for lint errors
npm run lint

# Auto-fix lint errors
npm run lint:fix

Commit messages

Local commits are validated by commitlint via a Husky commit-msg hook. Use the Conventional Commits format:

type(scope): description

Keep commits focused -- group related changes together in a single commit. For example, a feature and its tests belong in the same commit, not split across separate ones.

Breaking changes

If a commit introduces a breaking change -- for example, removing an endpoint, renaming an environment variable, or changing request/response schemas -- add a BREAKING CHANGE: footer to the commit body:

feat(link-resolution)!: remove legacy redirect mode

BREAKING CHANGE: The `legacyRedirect` query parameter has been removed.
Clients relying on this parameter must update to use the standard
resolution flow.

The ! after the type/scope is a shorthand marker that signals a breaking change in the commit subject. The BREAKING CHANGE: footer provides a description of what changed and what consumers need to do.

Breaking changes trigger a major version bump under semantic versioning.

Testing requirements

All modified and new functionality must have tests. The CI pipeline enforces a minimum coverage threshold of 80% across branches, functions, lines, and statements.

What needs tests

ChangeTesting requirement
New feature or moduleUnit tests covering core logic and edge cases
Bug fixA regression test that would have caught the bug
Modified behaviourUpdated existing tests plus new tests for changed behaviour
New utility functionUnit tests covering happy path and edge cases
RefactoringExisting tests must still pass; add tests if coverage gaps exist

Running tests

All test commands are run from the app/ directory. For full setup instructions, see the Development Setup page.

# Unit tests
npm test

# Unit tests in watch mode
npm run test:watch

# Unit tests with coverage report
npm run test:cov

# E2E tests (requires Docker Compose running)
npm run test:e2e -- --forceExit

E2E tests

info

End-to-end tests require a running MinIO instance and a running application server. The simplest approach is to start both with Docker Compose.

docker compose up -d
cd app
npm run test:e2e -- --forceExit

E2E test specs live in app/test/ and use a separate Jest configuration (app/test/jest-e2e.json). For more detail on running tests, see the Development Setup page.

Documentation contributions

The documentation site is built with Docusaurus and lives in the documentation/ directory.

Local development

cd documentation
yarn install
yarn start

This starts a local server with hot reload.

Building

yarn build

The CI pipeline builds the documentation on every pull request, so build failures will block your PR.

Documentation versioning

The documentation site supports versioned snapshots. You generally don't need to worry about versioning -- just edit the files in documentation/docs/. Versioned snapshots are created as part of the release process when the docVersion is bumped.