diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f0804dc23..5e12f1856 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -31,9 +31,13 @@ // Use 'forwardPorts' to make a list of ports inside the container available locally. // This can be used to network with other containers or with the host. - "forwardPorts": [3000, 3001, 5432, 8000], + "forwardPorts": [1025, 3000, 3001, 5432, 8000, 8025], "portsAttributes": { + "1025": { + "label": "Mailpit SMTP", + "onAutoForward": "silent" + }, "3000": { "label": "Application Backend", "onAutoForward": "silent" @@ -49,6 +53,10 @@ "8000": { "label": "PGAdmin", "onAutoForward": "silent" + }, + "8025": { + "label": "Mailpit", + "onAutoForward": "silent" } }, diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 028a007ec..01f4227a9 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -37,6 +37,24 @@ services: POSTGRES_USER: postgres POSTGRES_DB: postgres + # A mail server that delivers nothing, which is what makes it useful: everything the wiki sends — + # a registration's confirmation link, a password reset, the admin area's test button — lands in a + # web inbox at http://localhost:8025 instead of somebody's mailbox. + # + # Configure it under Admin -> Mail: host `localhost`, port 1025, TLS off, no username or password. + # Sharing the database container's network namespace is what makes `localhost` reach it. + mailpit: + image: axllent/mailpit:latest + restart: unless-stopped + environment: + # -> Nothing here is reachable from outside the container, and a dev instance should not fail a + # send because of a credential nobody has set: any AUTH is accepted, over a plain connection. + - MP_SMTP_AUTH_ACCEPT_ANY=true + - MP_SMTP_AUTH_ALLOW_INSECURE=true + # -> Deliberately no volume: these are test messages, and a mailbox that survives a rebuild is a + # mailbox full of last month's password resets. + network_mode: service:db + pgadmin: image: dpage/pgadmin4:latest environment: diff --git a/CLAUDE.md b/CLAUDE.md index 486d2fc69..3d649f754 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,11 @@ The backend is **TypeScript 7**; `frontend/` and `blocks/` are JavaScript. See `assets/_assets/`. Served by the backend. Don't hand-edit. - `dev/` — deployment/packaging artifacts: `dev/build/Dockerfile` (production image), `dev/helm/`, `dev/packer/`, `dev/noto-emoji-build/`. -- `.devcontainer/` — VS Code dev container (app + postgres + pgAdmin via docker-compose). +- `.devcontainer/` — VS Code dev container (app + postgres + pgAdmin + mailpit via docker-compose). + Mailpit is the mail server for development: it accepts everything and delivers nothing, so a + confirmation link or a password reset lands in a web inbox at `http://localhost:8025` rather than a + real mailbox. Point the wiki at it under **Admin → Mail** — host `localhost`, port 1025, TLS off, + no credentials. - `localazy.json` — translation sync config; locale strings live in `backend/locales/`. ### `backend/` @@ -722,17 +726,15 @@ store; no SVG is ever written into content. An earlier iteration of 3.x used GraphQL/Apollo. **All of it is deprecated** — there is no GraphQL server left in `backend/`, and `APOLLO_CLIENT` is not defined as a global, so any call still going -through it throws. `blocks/block-index/` also still imports a `tree.graphql`. +through it throws. -Three files under `frontend/src/` make live `APOLLO_CLIENT` calls, and each needs a REST endpoint -that does not exist yet, so the feature behind it is currently broken: +**One call is left.** `pages/AdminNavigation.vue`'s `save()` sends the navigation tree and its mode +through `APOLLO_CLIENT.mutate`, so saving the navigation is broken until it is ported. Nothing else +under `frontend/src/` references the global. That handler needs more than the endpoint, mind: it also +calls `this.$store.commit(...)` nine times over, and the file is `