# Contributing to nest-dmc

This guide is the **team working agreement** for the DMC Ops Platform backend.
Until GitHub Team plan is enabled (branch protection is paid for private repos
on Free plan), these rules are convention-enforced, not technically enforced.
**The CI pipeline runs on every PR — please respect its results.**

For the full engineering rule set see [.claude/rules/](.claude/rules/) and the
project [.claude/CLAUDE.md](.claude/CLAUDE.md).

---

## TL;DR

1. Branch off `main`
2. One commit per completed feature, conventional message
3. Open a PR — wait for CI green
4. Request review from an owner (CODEOWNERS auto-assigns)
5. Squash-merge when approved + green
6. Delete the branch

**Never** push directly to `main`. **Never** merge a red PR.

---

## Branch policy

- `main` is **always stable** — deployed to dev server (`dmc.workzy.co`)
- All work happens on short-lived branches:
  - `feature/<short-name>` — new functionality
  - `fix/<short-name>` — bug fix
  - `refactor/<short-name>` — non-behavioral cleanup
  - `chore/<short-name>` — tooling / deps / docs / CI
- Push the branch to remote for backup before opening the PR
- Delete the branch after merge — keep the remote tidy

---

## Commit messages — Conventional Commits

Format: `<type>(<optional scope>): <short summary>`

Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `test`, `perf`, `style`, `ci`

Examples:
- `feat(booking): add Movement Chart driver-day view`
- `fix(query): tax breakdown drift on multi-currency`
- `chore(deps): npm audit fix — resolve 4 transitive vulnerabilities`
- `refactor(common): extract DialogActions shared component`

Rules:
- One commit per completed feature — never partial work
- No `console.log`, no commented-out code, no secrets, no `.env` files
- Sign-off optional but encouraged

---

## Pull request checklist

Before requesting review:

- [ ] CI is green — all 9 enforcing jobs pass (lint, build, test, gitleaks, npm audit, OWASP, license, SonarCloud, CI Summary)
- [ ] `npm run build` passes locally
- [ ] `npm run lint:ci` passes locally (`--max-warnings=0`)
- [ ] `npm run test:ci` passes locally (no quarantine — every `*.spec.ts` must pass)
- [ ] PR description explains **why**, not just **what**
- [ ] If touching tenant-aware code: explicit note that isolation is preserved
- [ ] If adding a new dep: justified in PR body + audited (`npm audit`)
- [ ] No unrelated formatting / refactoring noise

## Review process

- CODEOWNERS auto-requests review when matching files change
- At least one owner approval is **expected** (not enforced)
- Reviewer checks for: tenant isolation, DTO validation, response envelope, security baseline ([.claude/rules/security.md](.claude/rules/security.md))
- Reviewer is responsible for the code review checklist in `security.md`

## Merging

- **Squash merge only** — keeps `main` history linear
- Delete the branch after merge
- The PR author handles the merge once approved + CI green
- If a merge introduces a regression, **revert via a new PR**, don't force-push

---

## CI gate — what each job means

| Job | Blocks merge? | What it does |
|---|---|---|
| Install Dependencies | yes | `npm ci` + cache |
| ESLint | yes | `--max-warnings=0` — any new lint issue blocks |
| Build (nest build) | yes | TypeScript compilation |
| Unit Tests + Coverage | yes | Jest, all suites required; ratchet floor 12/10/8/12 |
| Secret Scan (Gitleaks) | yes | Scans full history for tokens/keys |
| npm audit | yes | Fails on `high` or `critical` CVEs |
| OWASP Dependency-Check | yes | Broader CVE scan than npm audit |
| License Compliance | yes | Blocks GPL/AGPL/SSPL contamination |
| SonarCloud Quality Gate | yes | Inherits org default QG; "small change" coverage waiver enabled |
| **CI Summary** | **yes** | Aggregate gate — required check once branch protection is on |

## Local pre-flight (recommended)

Run all blocking checks before pushing:

```bash
npm ci
npm run build
npm run lint:ci
npm run test:ci
npm audit --omit=dev --audit-level=high
```

---

## Dependency upgrades

Per [.claude/rules/base.md](.claude/rules/base.md):

- **Ask before any upgrade** — patch, minor, or major
- **Major version bumps** — read the CHANGELOG; call out breaking changes
- **`npm audit fix --force` is forbidden** — silent major bumps break things
- **Post-upgrade smoke test (required):** `tsc --noEmit`, `npm run build`, `npm test`, manual hit on login + one GET + one save
- **Never** skip hooks with `--no-verify` on a dep commit

Dependabot opens grouped PRs weekly. The maintainers triage them:

- Patches + minors + dev-deps + GitHub Actions → batch-merge after CI green
- Majors (TypeScript / NestJS / TypeORM / ESLint) → dedicated session each

---

## What lives where

| Concern | Where |
|---|---|
| Engineering rules (folder structure, naming, DRY, security) | [.claude/rules/](.claude/rules/) |
| Multi-tenancy, branding, theming | [.claude/rules/tenancy.md](.claude/rules/tenancy.md) |
| RBAC, permissions, self-protection | [.claude/rules/governance.md](.claude/rules/governance.md) |
| Security baseline (OWASP Top 10) | [.claude/rules/security.md](.claude/rules/security.md) |
| Backend module structure (NestJS) | [.claude/rules/backend.md](.claude/rules/backend.md) |
| Frontend rules (React) | [.claude/rules/frontend.md](.claude/rules/frontend.md) |
| Project scope + phase tracker | `docs/dmc_scope.md` (in `docs-dmc` repo) |

---

## When in doubt

Stop and ask. The confirmation triggers in [.claude/rules/base.md](.claude/rules/base.md) are:

- Routing structure changes
- Global state / context shape changes
- Architecture or folder structure changes
- Shared components used across multiple pages
- New dependency installation
- Auth or permission logic changes

A 30-second question to an owner beats a 30-minute revert.
