Files
baya-monorepo/docs/rules/shared/git-and-gates.md
T
2026-07-30 02:26:52 +03:30

5.8 KiB

Git and the quality gates

What must pass before work is done, and what the repo refuses to let you commit.

Last verified: 2026-07-30 against commit d3ec723.


1. The gates

Each project is built, linted, and tested on its own. There is no root-level build, package, or solution, so there is no single command that gates the repo. Run the gate for the side you edited.

Client — cd client

Command What it runs
npm run check The gate. typelintlint:copy, in that order
npm run type tsc --noEmit (strict on)
npm run lint eslint . (flat config)
npm run lint:copy node scripts/check-copy.mjs — greps fa.json for banned Persian orthography variants
npm run test:ci jest --cialso required when you touched a component with a co-located *.test.tsx

npm run check must be green. en.json and fa.json must be in sync.

lint:copy is part of check, not a separate step you can forget. It is what stops a copy regression — a hamza-less «تایید», a space in the brand name — from needing to be re-discovered by a human. The rules it enforces are in client/i18n.md.

Server — cd server

Command What it runs
dotnet build Baya.sln Zero new warnings. Unused usings, locals, parameters, private fields or members count as failures — delete them, don't suppress them
dotnet test Baya.sln All tests pass, including the ones your change adds

A reachable SQL Server is required to run the API (not to build or unit-test it).

Both

Read your own diff as if you were reviewing the PR: would a senior engineer approve it without comment? A change that passes the mechanical gate and fails that question is not done.


2. What "done" means

A change is done when all of these hold:

  • The full scope is implemented. No // TODO: implement later, no stub that returns fake data. Anything not real is behind a DI-registered seam and recorded (see code-quality.md).
  • It follows the rules for that project — the relevant CLAUDE.md plus the one reference file for the area you touched.
  • No dead code. Comments explain why, not what.
  • The project's own gate above is green.
  • If the structure changed, the matching architecture section is updated in the same change (see documentation.md §3).
  • If a business rule was discovered or decided, product/ reflects it — recorded, not invented.
  • If a new reusable pattern or seam landed, the reference file for that area names it, so the next change reuses it instead of reinventing it.

A change that doesn't pass its own gate is not done, regardless of how complete the code looks.


3. The pre-commit secret scan

Repo-managed hooks live in .githooks/ (in version control, unlike .git/hooks). Enable them once per clone:

git config core.hooksPath .githooks

pre-commit is a fast, dependency-free backstop against a credential leaking into a file that shouldn't hold one. It scans only staged additions, so it is quick. It rejects a commit that stages:

  • the retired hardcoded admin password qw123321, anywhere;
  • private-key material or an AWS access-key id, anywhere;
  • the deployment's SQL Server host 87.107.152.16 outside the declared config files;
  • a real connection-string password in any appsettings*.json outside the declared config files (elsewhere only the SET_VIA_USER_SECRETS_OR_ENV placeholder is allowed).

The declared-config allow-list

The pre-launch demo deployment configures itself from committed files rather than a secret store (see DEPLOY.md), so a short allow-list is exempt from the last two checks:

appsettings.Development.json · docker-compose.yml · telegram-otp-bot/.env.example · DEPLOY.md

It is maintained in the declared_config function in the hook, and it is the honest record of where this repo's secrets are. Shrink it, never grow it. Once real users exist, those values must be rotated and moved out of git.

Limits

This is the local first line of defence, not a replacement for a full scanner (gitleaks, trufflehog) in CI. Bypass a false positive with git commit --no-verify — sparingly, and only when you are certain the flagged line is not a secret.


4. Branches and commits

main is the default branch and the base for PRs.

  • Commit or push only when asked. If you are on main and about to commit, branch first.
  • One coherent change per commit. The repo's history reads as a sequence of completed units of work (ui phase 11, remove user-secrets approach & prepare a pilot deploy) — keep that.
  • Never skip hooks (--no-verify) or bypass signing unless explicitly asked. If a hook fails, fix the underlying issue.
  • Prefer a new commit over amending an existing one.
  • Before a destructive git operation (reset --hard, push --force, checkout --), consider whether a safer route reaches the same place.

5. Known pre-existing warnings

These are expected and must not be "fixed" unless a task says so — a change that touches them is scope creep, and one that silences them is worse.

Warning Project Note
NU1510 on Microsoft.Extensions.Logging.Debug Baya.Web.Api Redundant transitive reference, harmless
NETSDK1057 (preview SDK) all server projects The .NET 10 SDK is preview on this machine

On the client, import/no-cycle is disabled in eslint.config.mjs (its TypeScript resolver has an interface mismatch with this toolchain), and ESLint is pinned to 9 — ESLint 10 crashes against this Next 16 toolchain with scopeManager.addGlobals is not a function. See client/testing.md.