# Test Environment This directory contains the Docker Compose setup and test data for local development. > **LLM agents:** read [AGENTS.md](./AGENTS.md) first. All commands below > are run from this `test/` directory. If you are working in a git > worktree alongside other worktrees of this repo, you must run > `./bootstrap-stack.sh` before `docker compose up` to avoid host port > collisions. One exception: the FedWiki HTTPS proxy (Caddy on `443`) is a > cross-stack singleton among stacks that compose it — see "Running multiple > isolated stacks" below. ## Quick Start ```sh cd test ./bootstrap-stack.sh docker compose up -d set -a; . .env; set +a go run .. start --config mc-config.yaml ``` That composes the **core** stack: Postgres, Valkey, Keycloak, Temporal. Every integration (FedWiki, Discourse) sits behind a compose profile and is off by default, so the console boots without them. To compose one, set the `COMPOSE_PROFILES` knob — either at bootstrap time: ```sh COMPOSE_PROFILES=fedwiki ./bootstrap-stack.sh ``` or by editing that one line in the generated `test/.env` and re-running `docker compose up -d`. Then uncomment that integration's `MC_*` block in the same file so the app is configured for it, not merely running beside it. See [`AGENTS.md`](AGENTS.md#which-integrations-the-stack-composes). To run the Go test suite against its own pristine databases (not the app's), use `make test` from the repo root. See [`AGENTS.md`](AGENTS.md#running-the-go-test-suite). ## Running multiple isolated stacks (parallel worktrees) `compose.yaml` accepts per-stack overrides via `.env`. The `bootstrap-stack.sh` helper generates one with a deterministic, collision-free port allocation derived from the worktree's directory name. Run the four Quick Start commands above in worktree A and worktree B — the two stacks coexist on disjoint host ports under separate `COMPOSE_PROJECT_NAME` namespaces. **Exception — the HTTPS farm is a singleton.** This applies only to stacks that select the `fedwiki` profile; core-only stacks never contend for the port. Browser access to FedWiki sites goes through a Caddy TLS proxy on host port `443` (`wiki-security-social` sets Secure cookies, which browsers only store over HTTPS). That port is fixed, not slot-allocated, so only one composing stack can serve browser login at a time — a second such stack's `caddy` container fails to bind `443` while the rest of its services come up normally. A slot-allocated port wouldn't help anyway: better-auth scopes cookies to the shared `*.localtest.me` domain (per-domain, not per-port — RFC 6265), so parallel stacks would clobber each other's session cookies regardless. Everything non-browser stays fully isolated: member-console's farm **API** calls use plain HTTP over the slot-allocated `FEDWIKI_PORT` with a bearer token (no cookies). True per-stack browser isolation needs a per-stack farm domain — tracked in [`status/issues.md`](../status/issues.md). To return a worktree to a clean state (containers + volumes + `.env` + `secrets/` + `testdata/`): ```sh ./teardown-stack.sh ``` See [AGENTS.md](./AGENTS.md) for the full contract, including the Stripe webhook constraint when running stacks in parallel. ## Services URLs below are the single-stack defaults; after `bootstrap-stack.sh` the host ports and `*.localhost` hostnames are per-stack (see the generated `.env`). Core services, always composed: | Service | URL | Credentials | |---------|-----|-------------| | Member Console | http://localhost:8081 | (via Keycloak) | | Keycloak | http://keycloak.localhost:8080 | admin / admin | | Temporal UI | http://localhost:8233 | (via Keycloak) | | PostgreSQL | localhost:5432 | member_console / member_console | | Valkey | localhost:6379 | — | Integration services, composed only when their profile is selected: | Service | Profile | URL | Credentials | |---------|---------|-----|-------------| | FedWiki (browser) | `fedwiki` | https://admin.localtest.me | (via Keycloak) | | FedWiki API | `fedwiki` | http://admin.localtest.me | (bearer token, see the MC_FEDWIKI_* block in `.env`) | | Discourse | `discourse` | http://discourse.localhost:9292 | (via Keycloak) | > **All credentials above are throwaway test-only values** — never reuse any of them in a real deployment. Browser access to FedWiki is HTTPS via the Caddy proxy (Caddy's internal CA — to trust it for manual browsing, export the root once: `docker compose cp caddy:/data/caddy/pki/authorities/local/root.crt ./caddy-root.crt`). See [AGENTS.md](./AGENTS.md) for the HTTPS/cert details. ## Test Data The `testdata/` directory is named like that so that gopls can ignore it by default. It contains sample data for testing the Member Console, such as: ### Keycloak Keycloak runs with `start-dev` (an ephemeral H2 database, no persistent volume). It does **not** import a realm file. Instead, the one-shot `keycloak-seed` service runs `seed/keycloak/seed-keycloak.sh` on every `docker compose up`, which — authenticating as the `master`-realm bootstrap admin — creates a dedicated **`test`** app realm and seeds its clients, roles, protocol mappers, client scopes, and test users over the Keycloak admin API (idempotent). App OIDC runs on `test`, not Keycloak's `master` admin realm, so the end-user account console works. Seeded into the `test` realm: - **Clients:** member-console, fedwiki, temporal-ui, temporal-authz (plus service accounts) - **Users:** alice (operator), bob, carlos, diana — password `password` To change the realm setup, edit `seed/keycloak/seed-keycloak.sh` — there is no realm export/import step. (An old `testdata/keycloak/master-realm.json` export remains on disk for reference but is untracked and unused by compose.) ### FedWiki Everything in this section applies only when the `fedwiki` profile is selected. FedWiki runtime data lives in `data/fedwiki/` (gitignored `status/` dirs). Seed data for owner files and access tokens is committed in `seed/fedwiki/`. A `fedwiki-init` container automatically copies seed files into `data/fedwiki/` on `docker compose up` without overwriting existing files (`cp -rn`). This means: - **Fresh clone:** seed data is copied in automatically, no manual steps needed. - **Existing setup:** your local data is preserved. To update seed data after making changes (e.g., new tokens or wiki sites): ```sh # Copy the relevant files from data/fedwiki/ to seed/fedwiki/ cp data/fedwiki//status/owner.json seed/fedwiki//status/ cp data/fedwiki//status/user-access-tokens.json seed/fedwiki//status/ ```