PR 0 of the router domain split (docs/website/API_V2_PLAN.md § Phase 2). The
split promises that admin.routes.js can be carved into one router file per
business capability without moving a single URL. That promise has to be proved
by a diff, not asserted in review — this lands the tool that proves it, with no
router file moved.
scripts/routeManifest.js walks the live Express stack (runtime introspection,
not source parsing: route paths in admin.routes.js sit on the line *after*
`adminRouter.get(`, which defeats greps) and writes a sorted { method, path }
list to routes.manifest.json. It reproduces the frozen baseline in
docs/website/api-route-inventory.json byte-for-byte — 199 public routes plus 2
on the internal listener — so the freeze is confirmed accurate, not just
claimed.
Scope is /api/** and /.well-known/** plus the internal app. The SPA catch-all,
/uploads and /brand are filesystem-conditional static mounts, so including them
would make the output depend on whether CI had built the client. Static mounts
are not API contract.
Also emits routes.guards.json — a review aid, not a contract: per route, the
handler count and the *named* middleware on its mount chain. Router-level
`use(noindex, isLoggedIn, staffOnly)` gates never appear in an individual
route's own stack, so an extracted capability router that forgot to re-apply
one would otherwise publish authenticated endpoints silently. Names are a hint
only (requireRole(...) returns an anonymous arrow), but a vanished requireAuth
is unambiguous — and the test suite asserts every /admin/** and /player/**
route still carries it.
The plan's optional unauthenticated-status snapshot was tried and dropped, as
it allowed: against the dead-port mariadb pool the tests use, the sweep sits on
the pool's acquire timeout and had not finished after two minutes. A flaky
two-minute gate is worse than none; the requireAuth assertion covers the same
regression deterministically.
CI runs `npm run routes:manifest -- --check` on every PR, so a URL change can
only merge by deliberately committing the new manifest.
Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
4.0 KiB
Markdown
101 lines
4.0 KiB
Markdown
# Contributing to Runic Gateway — Website
|
|
|
|
Thanks for your interest in contributing! This repo is the full-stack website
|
|
(Node.js + Express API, MariaDB, React + Vite SPA). This guide covers how to get
|
|
set up, the workflow we follow, and the rules for contributions.
|
|
|
|
By participating you agree to abide by our
|
|
[Code of Conduct](CODE_OF_CONDUCT.md).
|
|
|
|
## Ways to contribute
|
|
|
|
- **Report a bug** or **request a feature** through the
|
|
[issue tracker](https://gitea.whitlocktech.com/RunicGateway/website/issues)
|
|
(issue templates are provided).
|
|
- **Improve the code or docs** by opening a pull request (see below).
|
|
- **Never** report a security vulnerability in a public issue — see
|
|
[SECURITY.md](SECURITY.md).
|
|
|
|
## Development setup
|
|
|
|
**Prerequisites:** Node.js 20+ and npm, plus Docker (for MariaDB).
|
|
|
|
The [README](README.md) has the full setup guide. The short version for local
|
|
development with hot reload:
|
|
|
|
```bash
|
|
# 1. Start a MariaDB the backend can reach
|
|
docker run -d --name rg-db -p 3306:3306 \
|
|
-e MARIADB_DATABASE=runic_gateway -e MARIADB_USER=runic \
|
|
-e MARIADB_PASSWORD=devpass -e MARIADB_ROOT_PASSWORD=rootpass mariadb:11
|
|
|
|
# 2. Backend (terminal 1)
|
|
cp server/.env.example server/.env # set DB_* , JWT_SECRET, ADMIN_USERNAME/PASSWORD
|
|
npm run install-all
|
|
npm run server # nodemon -> http://localhost:3000
|
|
|
|
# 3. Frontend (terminal 2)
|
|
npm run client # Vite -> http://localhost:5173
|
|
```
|
|
|
|
Develop against **http://localhost:5173** (the Vite dev server proxies `/api`).
|
|
|
|
### Tests & checks
|
|
|
|
Please run the server test suite and make sure the client builds before opening
|
|
a PR — these are the same checks CI runs on your PR:
|
|
|
|
```bash
|
|
npm test # server tests
|
|
npm run build # client production build
|
|
```
|
|
|
|
If you add or change an API route, regenerate the Swagger spec
|
|
(`cd server && npm run swagger`) and commit the updated
|
|
`server/swagger/swagger-output.json`.
|
|
|
|
The URL surface is also frozen by a generated manifest. If your change adds,
|
|
removes or renames a route, regenerate it (`cd server && npm run routes:manifest`)
|
|
and commit `server/routes.manifest.json` + `server/routes.guards.json` — CI fails
|
|
otherwise. A non-empty diff in `routes.manifest.json` means you changed the API
|
|
contract, so call it out in the PR description; a pure refactor must produce none.
|
|
|
|
## Branch & PR workflow
|
|
|
|
1. Fork or branch from `main`. Use a descriptive branch name
|
|
(`feature/…`, `fix/…`, `docs/…`, `chore/…`).
|
|
2. Keep changes focused; small PRs are easier to review.
|
|
3. Push and open a pull request against `main`. Fill out the PR template,
|
|
including the **AI-assisted contributions** disclosure.
|
|
4. Make sure PR checks (server tests + client build) are green.
|
|
5. A maintainer will review; address feedback by pushing follow-up commits.
|
|
|
|
### Commit messages
|
|
|
|
We use [Conventional Commits](https://www.conventionalcommits.org/) —
|
|
`type(scope): summary` (e.g. `feat(auth): add TOTP challenge step`,
|
|
`fix(brand): link footer badge to Gitea org`). Common types: `feat`, `fix`,
|
|
`docs`, `chore`, `refactor`, `test`, `ci`.
|
|
|
|
## AI-assisted contributions (disclosure required)
|
|
|
|
This project is developed openly with AI assistance, and we ask the same
|
|
transparency of everyone. **If you used an AI tool** (Claude, Copilot, ChatGPT,
|
|
Cursor, etc.) to help produce a contribution, you must disclose it:
|
|
|
|
- Tick the AI-usage box in the pull-request template and name the tool(s).
|
|
- Mark AI-authored commits with a trailer, e.g.
|
|
`Co-Authored-By: Claude <noreply@anthropic.com>` or `Assisted-By: <tool>`.
|
|
- You remain responsible for every line you submit: review it, understand it,
|
|
and make sure it is correct and that you have the right to contribute it.
|
|
|
|
Disclosed AI assistance is welcome. Undisclosed AI-generated contributions are
|
|
not, and may be closed.
|
|
|
|
## License
|
|
|
|
Runic Gateway is licensed under the **GNU General Public License v3.0 or later**
|
|
(see [LICENSE.md](LICENSE.md)). By submitting a contribution you agree that it is
|
|
licensed under the same terms (inbound = outbound) and that you have the right to
|
|
contribute it.
|