feat(dev): add one-command local Stalwart test server + workflow docs

Add docker-compose.yml: a disposable Stalwart instance with a fixed dev
admin account (STALWART_RECOVERY_ADMIN), matching the credentials
scripts/dev-token.ps1 already expected. Wired up via new npm scripts
(dev:server, dev:server:down, dev:server:logs).

scripts/dev-token.ps1 was previously untracked (the whole scripts/
directory was gitignored) even though it's part of the documented dev
workflow — un-ignored it, and added scripts/dev-token.sh, a POSIX
equivalent for non-Windows shells and AI agents without PowerShell.

New DEVELOPMENT.md documents the full loop end-to-end (start server,
get a token, run the dev server, verify), written so it's actionable by
both humans and AI coding agents without needing a browser. Linked from
AGENTS.md (Commands) and README.md (Getting started).

Verified manually: docker compose up brings the server to a healthy
state, /api/auth + /auth/token issue a working bearer token, and
/jmap/session returns 200 with it end-to-end.
This commit is contained in:
Steven RYDELL
2026-08-01 18:05:43 +02:00
parent 38abba39f8
commit f4c8f8f21c
8 changed files with 277 additions and 4 deletions
+108
View File
@@ -0,0 +1,108 @@
# Development
How to run a local Stalwart test server and develop this WebUI against it.
This file is meant to be read by humans and AI coding agents alike — see
[AGENTS.md](AGENTS.md) for the rules that also apply while doing this.
## Prerequisites
- Node.js 18+
- Docker (with the `docker compose` CLI plugin)
## 1. Start a local test server
```bash
npm run dev:server
```
This runs `docker compose up -d`, which starts a disposable Stalwart
instance ([`docker-compose.yml`](docker-compose.yml)) with:
- The management/JMAP HTTP API on `http://localhost:8080` (the only port
the WebUI dev proxy needs — see `server.proxy` in
[`vite.config.ts`](vite.config.ts)).
- Mail protocol ports (SMTP/IMAP/POP3/ManageSieve) exposed too, only
needed if you're testing actual mail flows, not just admin UI screens.
- A fixed admin account baked in via `STALWART_RECOVERY_ADMIN`:
`admin@example.org` / `c8321iEscHDy0GWV`. **Disposable dev credentials
only — never reuse them for anything real.**
- Named Docker volumes (`stalwart-etc`, `stalwart-data`) so data survives
a restart. Data persists until you tear the volumes down.
Useful companions:
```bash
npm run dev:server:logs # tail the container's logs
npm run dev:server:down # stop it (add `-v` via `docker compose down -v` to also wipe data)
```
The server takes a couple of seconds to come up; `docker compose logs stalwart`
will show `Network listener started ... localPort = 8080` once it's ready.
## 2. Get an access token
The WebUI normally authenticates through an OAuth flow in the browser, but
for local development it's simpler to skip that and use a bearer token
directly via `VITE_ACCESS_TOKEN` (see `.env.development`).
```bash
# Windows / PowerShell
pwsh ./scripts/dev-token.ps1
# Linux / macOS / any POSIX shell (including most AI agent sandboxes)
bash ./scripts/dev-token.sh
```
Both scripts log in as the dev container's admin account, run the full
OAuth PKCE flow against it, and write the resulting token to
`.env.development.local` (gitignored, never committed). Tokens expire
after 1 hour — re-run the script and restart `npm run dev` if the UI
starts returning 401s.
## 3. Run the WebUI
```bash
npm install # first time only
npm run dev
```
Open `http://localhost:5173`. You should land directly in the admin panel
(no login screen) since `VITE_ACCESS_TOKEN` is set.
## 4. Verify your change
```bash
npm run typecheck
npm run lint
npm test
npm run build
```
For UI changes, actually look at the running app (browser or a browser
automation tool) — passing typecheck/lint/tests proves the code compiles
and existing behavior didn't regress, it doesn't prove the new UI works.
## Resetting the test server
To start from a completely clean server (e.g. to re-test first-run
behavior):
```bash
npm run dev:server:down
docker compose down -v # also removes the stalwart-etc/stalwart-data volumes
npm run dev:server
```
## Notes for AI agents
- This whole workflow (steps 13) is scriptable end-to-end without a
browser: `npm run dev:server`, then `bash scripts/dev-token.sh`, then
the app is reachable at `http://localhost:5173` with
`VITE_ACCESS_TOKEN` already set. Verify backend connectivity directly
with `curl`, e.g. `curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/jmap/session`.
- Read [AGENTS.md](AGENTS.md) before touching anything under `src/`
the schema-fidelity rule applies to all development, local test server
or not.
- Don't commit `.env.development.local` (it holds a live token) or leave
the dev container running unexpectedly — `npm run dev:server:down` when
you're done.