Thank you for considering a contribution to OpenCred! This document explains how to set up the project locally, how work is organised into issues, and the conventions every contributor should follow so the codebase stays clean and welcoming.
- Code of Conduct
- How to Find Work
- Development Setup
- Branch & Commit Conventions
- Architecture Overview
- Module Responsibilities
- Adding a Feature
- Writing Tests
- Pull Request Process
- Environment Variables
By participating in this project you agree to abide by the Contributor Covenant Code of Conduct. Be respectful and constructive in all interactions.
Issues are the single source of truth for contributor tasks.
| Label | Meaning |
|---|---|
good first issue |
Small, self-contained, well-scoped |
help wanted |
Open for any contributor to pick up |
feat: auth |
Scoped to the AuthModule |
feat: credentials |
Scoped to the CredentialsModule |
feat: blockchain |
Soroban / Stellar integration work |
feat: ipfs |
IPFS integration work |
feat: verification |
Credential verification workflow |
infra: postgres |
PostgreSQL + TypeORM setup |
infra: swagger |
OpenAPI / Swagger documentation setup |
bug |
Bug fix |
Before starting work, comment on the issue to let others know you are picking it up. This avoids duplicate effort.
- Node.js 20 or later
- npm 10 or later
- Git
# 1. Fork and clone
git clone https://github.com/<your-fork>/opencred-api.git
cd opencred-api
# 2. Install dependencies
npm install
# 3. Configure environment
cp .env.example .env
# Edit .env with your local values
# 4. Start the dev server (hot-reload)
npm run start:devThe API will be available at http://localhost:3000/api.
feat/<short-description> # new feature
fix/<short-description> # bug fix
refactor/<short-description> # non-functional change
docs/<short-description> # documentation only
test/<short-description> # tests only
Follow Conventional Commits:
feat(credentials): add IssueCredentialDto with class-validator decorators
fix(auth): handle expired JWT tokens gracefully
refactor(common): extract pagination helper into CommonService
docs(contributing): clarify branch naming rules
test(users): add unit tests for UsersService.findAll
src/
├── config/ Environment configuration factory
├── auth/ Authentication & JWT
├── users/ Platform user accounts
├── issuers/ Registered credential issuers
├── credentials/ Credential lifecycle (issue, retrieve, revoke)
├── verification/ Credential verification workflow
├── blockchain/ Stellar / Soroban smart-contract integration
├── ipfs/ IPFS storage integration
├── common/ Shared guards, filters, interceptors, pipes, decorators
└── health/ Health-check endpoint
Each module is intentionally isolated. Cross-module communication happens only through injected services — never through direct imports of controllers.
| Module | Responsibility |
|---|---|
auth |
Login, JWT issuance, token refresh, Stellar wallet challenge-response |
users |
CRUD for platform user accounts |
issuers |
Registration and status management for credential-issuing orgs |
credentials |
Issuance, retrieval, and revocation of all credential types |
verification |
Orchestrates IPFS fetch + on-chain status check for verification |
blockchain |
All Stellar SDK and Soroban contract calls (single integration point) |
ipfs |
All IPFS uploads and retrievals (single integration point) |
common |
Shared utilities — guards, filters, interceptors, pipes, decorators |
health |
Liveness endpoint for infrastructure monitoring |
- Pick up an issue and comment to claim it.
- Create a branch:
feat/<module>-<short-description>. - Locate the relevant
TODOcomment in the service or controller file. - Implement only the scope described in the issue.
- Add or update DTOs in the module's
dto/folder usingclass-validator. - Write unit tests (see Writing Tests).
- Run
npm run lint— the pipeline will fail on lint errors. - Open a pull request against
main.
Unit tests live alongside the source file they test:
src/credentials/credentials.service.spec.ts
src/credentials/credentials.controller.spec.ts
Use @nestjs/testing and Jest:
import { Test, TestingModule } from "@nestjs/testing";
import { CredentialsService } from "./credentials.service";
describe("CredentialsService", () => {
let service: CredentialsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [CredentialsService],
}).compile();
service = module.get<CredentialsService>(CredentialsService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
});Run tests:
npm run test # all tests once
npm run test:watch # watch mode
npm run test:cov # coverage report- Ensure
npm run testandnpm run lintboth pass locally. - Fill in the pull request template completely.
- Link the issue your PR resolves using
Closes #<issue-number>. - Request a review from a maintainer.
- Address all review comments before merging.
- Squash commits if the maintainer asks for it.
All environment variables are documented in .env.example.
Never commit a .env file. The .gitignore already excludes it.
If you need a new variable, add it to .env.example with a placeholder value
and document it here.
Thank you for contributing to OpenCred!