Thanks for taking the time to contribute. This guide covers everything you need to get a working local environment, run the test suite, and get your PR reviewed.
- Node.js 20.x (see
.nvmrcor usenvm use 20) - npm 10+ (bundled with Node 20)
- PostgreSQL 16 (or use the provided Docker Compose setup)
- Git
Optional but recommended:
- Docker + Docker Compose (simplifies database setup)
- k6 for load tests
git clone https://github.com/Ethereal-Future/FuTuRe.git
cd FuTuRe
npm installcd backend
cp .env.example .envOpen backend/.env and fill in the required values. At minimum you need:
DATABASE_URL— PostgreSQL connection stringJWT_SECRET— any strong random string for local devSTREAM_SECRET_ENCRYPTION_KEY— 32-byte hex key (see comment in.env.example)
See backend/CONFIGURATION.md for the full reference.
Using Docker (recommended):
# from the repo root
docker compose up db -dOr point DATABASE_URL at an existing local PostgreSQL 16 instance.
cd backend
npx prisma migrate deployFrom the repo root:
npm run devThis starts both servers concurrently:
| Service | URL |
|---|---|
| Backend | http://localhost:3001 |
| Frontend | http://localhost:3000 |
The backend uses --watch for hot-reload. The frontend uses Vite HMR.
npm run test:coveragenpm run test --workspace=backendRequires a running PostgreSQL instance (use docker compose up db -d):
npm run test:db --workspace=backendnpm run test:contractsnpm run test:propertyRequires k6 and a running backend:
npm run load-test:endpoints --workspace=backend
npm run load-test:concurrent --workspace=backend
npm run load-test:regression --workspace=backendThe backend connects to the Stellar testnet by default. To run against it:
- Set these values in
backend/.env:
STELLAR_NETWORK=testnet
HORIZON_URL=https://horizon-testnet.stellar.org- Start the backend:
npm run dev:backend- Create a test account via the frontend or the API — new accounts are automatically funded by Friendbot.
Never use real Stellar mainnet keys in development. The testnet is reset periodically; any balances will be lost.
-
Fork the repo and create a branch from
main:git checkout -b feat/your-feature-name
-
Make your changes. Keep commits focused — one logical change per commit.
-
Ensure all checks pass locally before pushing:
npm run test:coverage npm audit --audit-level=high
-
Push your branch and open a pull request against
main. -
Fill in the PR template. Include:
- What the change does and why
- How you tested it
- Any follow-up work or known limitations
-
A maintainer will review within a few business days. Address feedback by pushing new commits — do not force-push after review has started.
-
Once approved, a maintainer will squash-merge your PR.
- Tests added or updated for new behaviour
-
npm run test:coveragepasses - No new high/critical vulnerabilities (
npm audit --audit-level=high) - Code formatted with
npm run format - PR description explains the change clearly
Use one of these prefixes followed by a short, kebab-cased description:
| Prefix | Use for |
|---|---|
feat/ |
New features |
fix/ |
Bug fixes |
docs/ |
Documentation-only changes |
chore/ |
Dependency bumps, tooling, config |
refactor/ |
Code restructuring without behaviour change |
test/ |
Adding or fixing tests |
Examples:
feat/gdpr-data-export
fix/refresh-token-expiry
docs/security-guide
The project uses ESLint and Prettier. Run the formatter and linter before pushing:
npm run format # applies Prettier
npm run lint # ESLint checkKey conventions:
- ES modules (
import/export) throughout — norequire(). - Async/await preferred over
.then()chains. - No unused variables;
_prefix for intentionally unused parameters. - Keep functions small and single-purpose; avoid deeply nested callbacks.
Follow the Conventional Commits specification:
<type>(<scope>): <short summary>
[optional body — explain *why*, not *what*]
[optional footer — e.g. Closes #123]
Types: feat, fix, docs, chore, refactor, test, perf.
Examples:
feat(auth): add GDPR data-export endpoint
Implements Article 15 right-of-access requirement.
Closes #503
fix(compliance): filter MEDIUM alerts from SAR reports
Issues labelled good first issue are well-scoped, self-contained tasks with clear acceptance criteria — ideal if you are new to the codebase.
To find them: go to Issues and filter by the good first issue label.
Before starting:
- Comment on the issue to let others know you are working on it.
- Ask any clarifying questions in the issue thread before writing code.
- Keep the PR focused on the acceptance criteria — avoid unrelated refactors.
All uses: references in .github/workflows/ must be pinned to a full commit SHA rather than a mutable version tag.
Why: A tag like actions/checkout@v4 can be silently moved to a different commit by the action author (intentionally or after a supply-chain compromise). If that commit contains malicious code it will execute with access to repository secrets. A pinned SHA is immutable — the exact code that was reviewed is the exact code that runs.
- Find the commit SHA for the version you want:
# Using gh CLI gh api repos/<owner>/<action>/git/refs/tags/<tag> --jq '.object.sha' # If the tag points to an annotated tag object, resolve it: gh api repos/<owner>/<action>/git/tags/<sha> --jq '.object.sha'
- Use the SHA in the workflow file with a human-readable comment:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- Dependabot (configured in
.github/dependabot.yml) will open PRs automatically when a new version is available, updating the SHA to the latest commit for the tag. Review the tag comment to confirm the version before merging.
- Check the action's CHANGELOG / release notes for the new version.
- Confirm the SHA in the PR matches the tag it claims (spot-check via
gh api). - Never approve a SHA update without verifying the tag it corresponds to.
npm audit --audit-level=high runs as a blocking CI step in both test.yml and security-pipeline.yml (covering the root workspace, backend/, and frontend/). A PR cannot merge if any high or critical vulnerability is present in the dependency tree.
Dependabot is configured (.github/dependabot.yml) to open weekly PRs for outdated packages across all three npm contexts and for GitHub Actions. These PRs are labelled dependencies and follow the normal review process.
- Run
npm auditlocally to read the full advisory:npm audit cd backend && npm audit cd frontend && npm audit
- Check the advisory severity, affected versions, and whether a patched version exists.
- If a fix is available, update:
npm audit fix # safe semver-compatible fixes npm audit fix --force # major-version bumps (review breaking changes first)
- If no upstream fix exists yet, assess exploitability in context. If the vulnerable code path is not reachable (e.g., a dev-only package never executed in production), document the exception in a comment on the advisory issue and set a reminder to re-evaluate in 30 days.
- Create a branch:
chore/fix-<package>-vuln. - Update the dependency and run the full test suite:
npm run test:coverage npm audit --audit-level=high
- Open a PR with the advisory ID in the description (e.g.,
Fixes GHSA-xxxx-xxxx-xxxx). - Request review from at least one maintainer — security patches are treated as priority reviews.
- Merge as soon as approved; do not batch security fixes with unrelated changes.
- Check the changelog / release notes for breaking changes before approving.
- Run
npm run test:coverageagainst the branch locally if the package is a critical runtime dependency. - If the update introduces a breaking change that cannot be resolved immediately, close the PR with a comment explaining the blocker and open a tracking issue.