Enable pageview tracking when VITE_UMAMI_WEBSITE_ID is set at frontend
build time (Forgejo secret + deploy workflow), with SPA route updates
and no script in local dev. Document setup in docs/umami-analytics.md,
extend integritetspolicy, and add admin Webbstatistik link in prod builds.
Co-authored-by: Cursor <cursoragent@cursor.com>
Deploy workflow now writes MAIL_* and APP_PUBLIC_BASE_URL from Actions
secrets into the server .env so Resend SMTP works after domain verify.
Document Resend-only setup, Forgejo secret names, and prod expose-token off.
Co-authored-by: Cursor <cursoragent@cursor.com>
Operators can fix prod admin passwords without email via Byt lösenord;
end users can use forgot-password when SMTP is configured. Local and CI
use Mailpit to capture outbound mail and verify reset links end-to-end.
- Backend: V8 password_reset_tokens, PasswordResetService, EmailService,
POST /api/auth/forgot-password, reset-password, change-password
- Optional testToken in forgot-password response (docker profile only, for E2E)
- Frontend: ForgotPasswordPage, ResetPasswordPage, ChangePasswordPage,
routes, login link, header Byt lösenord
- Mailpit (ghcr.io/axllent/mailpit:v1.28) in docker-compose + e2e stack
- E2E: password-reset.spec.ts + Mailpit API helper tests SMTP delivery
- Separate dev/e2e Docker image names to avoid overwriting bilhej-frontend
- Docs: README email section, production-email-checklist, .env.example
- Unit/integration tests for reset, change password, and Vitest page specs
Co-authored-by: Cursor <cursoragent@cursor.com>
Production must not ship test users, demo orders, or test1234. Dev and CI
still need seeded users for e2e. Prod creates one admin from deploy secrets.
- Move V2/V4/V6 seed migrations to db/dev-migration
- Add application-prod.yml with schema-only Flyway and ignore-missing for moved seeds
- Add AdminBootstrap to create admin from ADMIN_EMAIL and ADMIN_PASSWORD
- Wire docker,prod profile, deploy secrets, and localhost:5433 for SSH DB access
- Add hashPassword Gradle task for optional manual bcrypt generation
Replace the mock test-payment button with a real manual Swish flow
where the user sends a Swish payment with the order ID as message
and confirms via a button. Admin verifies Swish and processes manually.
Backend
- Rename OrderStatus LOOKUP_STARTED to PROCESSING (Swedish: Hanteras)
- Update V5 migration CHECK constraint from lookup_started to processing
- Rename OrderService.markAsPaid() to confirmPayment(), sets PROCESSING
instead of PAID, stop hardcoding amountPaid
- Add GET /api/payment/swish-info endpoint returning swish number and
letter price from app.payment config
- Permit /api/payment/swish-info without authentication
- Update UpdateStatusRequest regex to accept processing
- Update PaymentControllerTest for renamed method, new status, and
public swish-info endpoint test
Frontend
- Rewrite PaymentRedirect.vue: Swish number, order ID as message,
Jag har betalat button with confirmation dialog
- Add fetchSwishInfo() to api/payment.ts
- AdminPage: rename Skickade stat to Att göra (processing orders),
highlight processing rows with admin__row--todo
- OrdersPage: update status labels/badge classes for new flow
- Refactor ApiError in client.ts to property declaration syntax
- Exclude __tests__ from tsconfig.app.json and Docker builds
Tests
- Rewrite PaymentRedirect.spec.ts for Swish info, confirmation dialog,
cancel flow, and processing status
- Update OrdersPage.spec.ts with processing status test
- Update AdminDashboard.spec.ts with Att göra stat and row highlight
- Add amountPaid to ComposePage.spec.ts mock
Config
- Add SWISH_NUMBER to .env.example and docker-compose.yml