mirror of
https://github.com/GainSec/RealHermes.git
synced 2026-10-23 11:00:49 +02:00
70 lines
6.1 KiB
Markdown
70 lines
6.1 KiB
Markdown
# Development
|
|
|
|
How the code is organized is described in [architecture.md](architecture.md#source-layout). This page covers working on it: commands, tests, conventions and CI.
|
|
|
|
## Commands
|
|
|
|
| Command | Purpose |
|
|
| --- | --- |
|
|
| `npm ci` | Install the exact locked dependencies. |
|
|
| `npm run dev` | Vite with hot reload on 127.0.0.1:5173 plus the relay on 127.0.0.1:3001 (`tsx watch`). |
|
|
| `npm run dev:full` | `npm run dev` plus a local `hermes serve` audio backend on 127.0.0.1:9119. |
|
|
| `npm test` | All tests once (Vitest). |
|
|
| `npx vitest run server/config.test.ts` | One test file; `npx vitest` watches. |
|
|
| `npm run lint` | oxlint (`.oxlintrc.json`). |
|
|
| `npm run build` | Type-check the client (`tsc -b`) and the server (`tsconfig.server.json`, strict), then the Vite production bundle in `dist/`. |
|
|
| `npm run verify` | The release gates: tests, lint, build, the Hermes plugin's Python tests and git whitespace checks (`scripts/verify.sh`). |
|
|
| `npm run doctor` | Read-only environment checks. |
|
|
| `npm run setup:env` | Create `.env` from `.env.example` if it does not exist. |
|
|
|
|
## Tests
|
|
|
|
The suite runs without network access, without Hermes and without binding ports, so it works in restricted CI sandboxes.
|
|
|
|
- **Relay:** real Express routing through an in-memory HTTP harness (`server/test-request.ts`), with injected `fetch`, DNS, transports, process runners, filesystems and clocks. It covers credential separation, routing, streaming, timeouts, sanitized errors, the artifact handoff (verification before `done`, dead-link recovery, `reset`), tool starts reported only as `working`, local file discovery (symlink, hidden, size, magic and parent-swap cases), SSRF and DNS rebinding boundaries, cache limits and response headers.
|
|
- **Transport:** real TLS and HTTP/2 servers on loopback with throwaway certificates generated at test time (`server/test-certificate.ts`), so no private key is stored in the repository.
|
|
- **Poppler:** unit tests use fake executables. `server/artifact-poppler.test.ts` renders a real two-page PDF when `pdfinfo` and `pdftoppm` are found the same way the server finds them, and is skipped otherwise.
|
|
- **Hermes plugin:** `hermes-plugins/steam-frame-view/tests` are Python `unittest` tests with a stand-in command runner; run `python3 -m unittest discover hermes-plugins/steam-frame-view/tests`. They never run SSH.
|
|
- **Launchers:** injected spawn, kill, ports, probes and fake timers. No test starts Hermes, SSH or a real child process. `scripts/hermes-production.test.ts` runs `python3` against stand-in Hermes modules, so `python3` must be on `PATH`.
|
|
- **Browser:** relay client, conversation states, SSE parsing and artifact logic as unit tests. The scene runs the real Simulator, panel, grab handles, OrbitControls and the pointer events from `@react-three/xr` in a real React Three Fiber root (`src/simulatorStage.tsx`), driven by DOM pointer events and staged XR controller sessions. Only WebGL, the model file, Troika text and the WebXR session are replaced.
|
|
|
|
WebGL rendering, real microphones, live Hermes integration and headset sessions need manual checks on the target browser or device.
|
|
|
|
## Conventions
|
|
|
|
- **Test first.** Write a failing test that names the behavior, watch it fail for the expected reason, then make it pass. Bug fixes start with a reproducing test.
|
|
- **Inject, don't mock globally.** Server and launcher code takes its dependencies (fetch, DNS, filesystem, clock, spawn, runners) as options; extend those seams rather than patching modules.
|
|
- **Fail closed and stay quiet.** Validate shapes and bounds at every boundary, return fixed sanitized messages, and never echo upstream bodies, keys, URLs, tool arguments or paths.
|
|
- **Server-only configuration.** New settings are read in `server/config.ts` (or the launchers), documented in `.env.example` and [configuration.md](configuration.md), and checked by `npm run doctor` when they can be misconfigured.
|
|
- **Synthetic fixtures only.** Use `example.com` and other reserved names, the documentation address ranges `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24` and `2001:db8::/32`, paths such as `/home/example` or `/srv/realhermes`, and invented names (the tests use a fictional mascot, "Numbix"). Never commit real hostnames, addresses, user names, paths, keys or captured frames. The SSRF tests deliberately list private and reserved ranges (`10.0.0.0/8`, `192.168.0.0/16` and so on) as addresses that must be refused.
|
|
- **Keep docs in step.** User-visible behavior changes update the relevant page under `docs/`.
|
|
|
|
## Release gate
|
|
|
|
`scripts/verify.sh` is the single gate: run `npm ci`, then `npm run verify`. The script runs the tests, lint, build and the plugin's Python tests. It then checks every committed file for whitespace errors against the empty tree (`git diff --check`), plus any unstaged or staged changes. It needs Node.js, npm, git, `python3`, and Poppler for the real PDF test. There is no hosted CI; run it locally before publishing.
|
|
|
|
### Running the gate in a Linux container
|
|
|
|
With Docker, from a committed checkout:
|
|
|
|
```sh
|
|
docker run --rm -v "$PWD:/src:ro" node:22-bookworm sh -c '
|
|
git config --global --add safe.directory /src/.git &&
|
|
git clone -q /src /work && cd /work &&
|
|
apt-get update -qq && apt-get install -y -qq --no-install-recommends poppler-utils >/dev/null &&
|
|
npm ci --no-audit --no-fund && npm run verify'
|
|
```
|
|
|
|
This clones only committed files into the container, so local `node_modules`, `.env` and other ignored files never enter it.
|
|
|
|
## Release checklist
|
|
|
|
Before publishing a release candidate:
|
|
|
|
1. `npm ci && npm run verify` passes (and the container recipe above, for Linux).
|
|
2. `npm run doctor` gives no failures on a prepared machine.
|
|
3. No secrets or private data are in tracked files. Review `git ls-files`, and search them for credentials, private keys, personal paths, private hostnames and addresses outside the documented test ranges.
|
|
4. No generated or local files are tracked: `dist/`, `node_modules/`, `.env`, captures, caches and logs are all git-ignored.
|
|
5. `public/models/realhermes-idle.glb` is present and loads in the desktop simulator.
|
|
6. Documentation links resolve, and changed behavior is reflected in `docs/`.
|