First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the Table of Contents for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved.
This project and everyone participating in it is governed by the Trellis API Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to conduct@trellis.example.
Before you ask a question, it is best to search for existing Issues that might help you. In case you have found a suitable issue and still need clarification, you can write your question in that issue. It is also advisable to search the internet for answers first.
If you still have questions, feel free to reach out via GitHub Discussions.
- Make sure that you are using the latest version.
- Check that your issue hasn't already been reported.
- Collect information about the issue to help us fix it quickly.
Use the bug report template to create a detailed issue. Include:
- A quick summary and/or background
- Steps to reproduce
- What you expected would happen
- What actually happens
- Notes (potentially including why you think this is happening)
Enhancement suggestions are tracked as GitHub issues. Create an issue and provide:
- A clear and descriptive title
- Step-by-step description of the suggested enhancement
- Current behavior vs. expected behavior
- Screenshots if applicable
- Explain why this enhancement would be useful
- Fork the repository
- Clone your fork
- Create a branch:
git checkout -b feature/your-feature-name - Make your changes
- Run tests:
npm test - Commit your changes
- Push to your fork
- Open a Pull Request
# Install dependencies
npm install
# Copy environment template
cp .env.example .env
# ── Run contributor diagnostics before starting ─────────────────────────────
# Checks your tools, environment variables, database, Redis, and external
# services. Always run this after cloning or updating your .env.
npm run diagnostics
# For a faster check that skips network probes:
npm run diagnostics:quick
# Details, failure modes, and safe recovery:
# docs/DEVELOPER_DIAGNOSTICS.md
# Start development server
npm run start:dev
# Run tests
npm run test
# Run linting
npm run lintIf you are working on the payment or chain integration and do not want to configure PostgreSQL, Redis, Stellar or Grantfox, use integration sandbox mode. It swaps the external payment dependency for deterministic fakes that need no secrets and never touch a real network or ledger.
# Run the full create → sign → submit → status → refund workflow, offline
npm run sandbox:demo
# Sandbox test suite
npm run test:sandboxContributors can generate seedable, repeatable test datasets covering standard user operations, edge cases, corrupt payloads, auth failure states, and boundary conditions.
# Generate deterministic fixtures with default seed (42) to stdout
npm run fixtures:generate
# Generate fixtures with custom seed and write output to file
npm run fixtures:generate -- --seed=12345 --output=test/fixtures/local.jsonSet SANDBOX_MODE=true in .env to enable it for the running API and select
the processor per request with X-Payment-Processor: sandbox (or
PAYMENTS_DEFAULT_PROCESSOR=sandbox). It is refused when
NODE_ENV=production. See docs/SANDBOX_MODE.md for the
available scenarios, configuration and limitations.
The API validates all required secrets at startup. Invalid or placeholder values cause a fast-fail with an actionable error message. See .env.example for the full list of supported variables.
Required for core functionality:
DATABASE_URL— PostgreSQL connection stringJWT_SECRET— 32+ character random string (generate withnode -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
Required for specific features:
REDIS_URL— Redis URL for rate limiting, caching, and Bull queuesSTELLAR_HORIZON_URL+STELLAR_SIGNING_SECRET— Stellar payment integrationOPENAI_API_KEY— AI compute featuresSMTP_HOST+SMTP_*— Email notifications
Production deployments additionally validate that secrets are not placeholders and that localhost URLs are not used.
All routes are served under /api/v1/... by default. Version 2 routes
(when introduced) are accessible at /api/v2/.... Deprecated routes will
carry Deprecation and Sunset HTTP headers pointing to migration guides.
Expensive operations (AI token usage, oracle submissions, file uploads, compute jobs) enforce per-user budget quotas. Administrators can inspect and reset quotas via:
GET /api/v1/admin/quota/policies— list all quota policiesGET /api/v1/admin/quota/usage/:resource— per-actor usage for a resourceGET /api/v1/admin/quota/peek?actor=…&resource=…— inspect a specific actorDELETE /api/v1/admin/quota/reset?actor=…&resource=…— reset an actor's quota
All admin quota endpoints require the ADMIN role.
docs/openapi.json is the published API contract: the Redoc reference published
by CI, the generated TypeScript/Python SDKs, and every third-party integration
read it. It is generated from the NestJS controller decorators, so it must be
regenerated and committed whenever a controller, route, DTO, @Api* decorator,
parameter, response or component schema changes.
# Regenerate the artefact from the current decorators
npm run openapi:export
# Verify that the committed artefact still matches the decorators
npx ts-node -r tsconfig-paths/register scripts/check-openapi-drift.tsThe check boots the Nest app in memory through the same code path
npm run openapi:export uses (scripts/lib/openapi-document.ts), builds the
document with the published metadata and deepScanRoutes: true, and diffs it
against docs/openapi.json member by member. The comparison is structural
rather than textual: key ordering and formatting are normalised away, while
added/removed paths, HTTP methods and operations, changed operation members
(summary, parameters, requestBody, responses, ...), changed component
schemas and changed document members such as info, servers or
securitySchemes are each reported with the path they belong to.
CI runs it in the openapi-drift job of
.github/workflows/build-check.yml on pull
requests and on pushes to main/master:
- Artefact identical to the decorators → the job passes.
- Any drift → the job fails and prints every differing path/operation plus
the three commands that fix it:
npm run openapi:export,git add docs/openapi.jsonand the commit. docs/openapi.jsonmissing, empty, not valid JSON, or without paths → the job fails with the same instructions, so deleting the artefact can never be a way to make the gate pass.
Both scripts/export-openapi.ts and the drift check import the document builder
from scripts/lib/openapi-document.ts; keep that the only place that knows how
the spec is assembled so the artefact and the gate cannot drift apart.
There is no npm run alias for the drift check yet - invoke the script directly
with npx ts-node as shown above (that is exactly what CI runs).
Run npm run diagnostics at any time to verify your local setup:
| Section | What it checks |
|---|---|
| Required tools | node ≥ 18, npm, git, docker (optional), psql (optional) |
| Dependencies | node_modules present, no critical npm audit findings |
| Environment | All required .env vars set with non-placeholder values |
| Database | TCP reachability + optional psql query |
| Redis | TCP reachability |
| Stellar Horizon | HTTP reachability (skipped with --quick) |
| SMTP | TCP reachability (skipped with --quick) |
| Build | TypeScript type-check via tsc --noEmit (skipped with --quick) |
| Tests | Runs diagnostics-related unit tests |
The command exits 0 on pass/warn and exits 1 on any failure. It never mutates any data.
You can help improve documentation by:
- Adding missing descriptions
- Fixing typos and grammar
- Adding tutorials and guides
- Improving existing documentation
Use conventional commits:
feat:for new featuresfix:for bug fixesdocs:for documentation changesrefactor:for code refactoringtest:for adding testschore:for build/tooling changes
Example: feat: add new wallet authentication provider
- Follow the existing ESLint configuration
- Use TypeScript types for all functions and variables
- Write comprehensive JSDoc comments for public APIs
- Keep functions small and focused
- Write unit tests for all new features
If you're interested in becoming a maintainer, reach out to the core team! We're always looking for passionate contributors to help grow the project.
Happy coding! 🚀