CONTRIBUTING.md
Rama main · réplica de lectura del repositorio original.
# Contributing to Rechvix
Thanks for considering a contribution. Rechvix is a real production-grade
platform, not a toy project — the bar for changes is "would I trust this
with a real business's books," and the review process reflects that.
## Before you start
Read [`README.md`](README.md) and [`docs/architecture.md`](docs/architecture.md)
first. The architecture doc explains *why* the codebase is shaped the way it
is (modular monolith, `NUMERIC` money, append-only stock ledger, double-entry
enforced at three layers, generic tax engine) — most "obviously simpler"
alternatives someone new to the codebase suggests are already covered there,
with the reasoning for why they weren't chosen.
For anything beyond a small fix, open an issue first describing what you want
to change and why, before writing code. It saves everyone time when a PR
turns out to conflict with a design decision or an in-progress stage.
## Development setup
Requires **Go 1.27+** (or let `go`'s toolchain auto-download it — `go.mod`
already pins the version) and a **PostgreSQL 18** instance, or Docker if you'd
rather not install Postgres locally.
```bash
git clone https://github.com/Raktim94/rechvix.git
cd rechvix
# Option A — your own local Postgres 18
export DATABASE_DSN="postgres://user:pass@localhost:5432/rechvix?sslmode=disable"
export DATABASE_AUTO_MIGRATE=true
go run ./apps/server
# Option B — Docker Compose (matches production topology)
cd deploy/compose
cp .env.example .env # fill in the required secrets, see comments in the file
docker compose up -d
```
Frontend (separate terminal):
```bash
cd apps/web
npm install
npm run dev # proxies /api to :8080 automatically, see vite.config.ts
```
Then open `http://localhost:5173/setup` to bootstrap your first organisation.
See `internal/platform/config/config.go` for every environment variable the
server reads — each has either a required source or a documented default,
and a missing required value fails fast at startup with a clear message.
## Running tests
```bash
go test ./... # unit tests, no external dependencies
go test -tags=integration ./... # integration tests — needs Docker (Testcontainers spins up real postgres:18)
```
Frontend:
```bash
cd apps/web
npm run lint # oxlint
npx tsc -b # TypeScript strict mode, must be zero errors
npm run build
```
A change isn't "done" until both unit and (where relevant) integration tests
pass, and the frontend still builds clean under strict TypeScript.
## Code conventions
- **Money is never `float32`/`float64`.** Always the internal `Money` type
wrapping `shopspring/decimal`, backed by `NUMERIC` columns. A PR that
introduces a float for anything money-shaped will be rejected outright —
see the README's "Core design decisions" table for why.
- **Module layering**: each `internal/modules/*` package follows
`domain/` (pure business rules, no I/O) → `app/` (use-case orchestration)
→ `pg/` (repository implementation) → `httpapi/` (HTTP handlers). Look at
`internal/modules/organisation` as the reference shape before adding a new
module or a new use case to an existing one.
- **Every tenant-scoped table** must be filtered by `organisation_id` at the
application layer *and* rely on PostgreSQL Row-Level Security — defense in
depth, not either/or (see `docs/adr/0006-getbyid-organisation-scoping.md`
for a real example of this being enforced after a gap was found).
- **Structured logging** via `log/slog`, never `fmt.Println`/`log.Print` in
application code.
- **No `UPDATE` on posted journal rows.** Accounting corrections are new
entries (reversals/adjustments), never in-place edits — this is enforced
at the database grant level, not just convention.
- **Government API adapters are versioned by directory** (`einvoice/v1`,
`.../vNext`, etc.) — a schema change from GSTN is a new adapter, not an
edit to an existing one that breaks anyone still on the old version.
## Commit messages
Short, imperative, specific about *what changed and why it mattered* — look
at `git log` for the house style. Good examples from this repo's own
history: `Fix critical bug: no real user could ever finalize an invoice
(found by actually running the app)`, `Security hardening: add
organisation_id filter to every GetByID (defense in depth)`. Avoid vague
messages like "fix stuff" or "update code."
## Opening a pull request
1. Fork the repo, branch off `main`.
2. Keep the PR focused — one logical change per PR is easier to review and
easier to revert if something's wrong.
3. Include tests for new behavior and for any bug fix (a regression test
that would have caught the bug, not just the fix itself).
4. Make sure `go build ./...`, `go vet ./...`, `go test ./...`, and the
frontend build/lint all pass locally before requesting review.
5. Describe *why* the change is needed, not just what it does — reviewers
need the reasoning to judge tradeoffs, not just read a diff.
## License
Rechvix is licensed under the [GNU Affero General Public License v3.0](LICENSE)
(AGPL-3.0). By contributing, you agree that your contributions will be
licensed under the same terms.
## Reporting security issues
Please do **not** open a public issue for a security vulnerability. Instead,
report it privately — see [`docs/architecture.md`](docs/architecture.md) for
the threat model this project is built against, and reach out via
[nodedr.com](https://www.nodedr.com/) for a private disclosure channel.