Repository navigation
v2.0
Full stack refresh: every technology moved to its current latest release, all known security alerts closed, build tooling rebuilt around make and Docker.
Upgrades
- JDK 21 -> Oracle JDK 27 (LTS line: 25; Boot 4.1.1 documents through JDK 26, the full build and app run green on 27)
- Spring Boot 3.2.4 -> 4.1.1 (Framework 7.0.9, Tomcat 11, Hibernate 7.4.5, Jackson 3.1.5, MySQL Connector 9.7.0)
- Maven wrapper 3.6.2 -> 3.9.16
- Angular 10.0.8 -> 22.2.1: standalone components, signals, control-flow templates, zoneless change detection, esbuild builder, functional interceptor, strictTemplates, vitest, eslint
- TypeScript 3.9.7 -> 6.0.3, rxjs 6 -> 7.8.2
- Bootstrap 4 (CDN + jquery + popper) -> Bootstrap 5.3.8 npm only
- ngx-bootstrap 5 -> 22.0.0, @ngx-translate 13 -> 18.0.0, ngx-spinner 10 -> 22.0.1, FontAwesome -> 7.x icon packages
- Build pin: frontend-maven-plugin 2.0.2 with Node 24.21.0 LTS
- xlsx 0.16.5 -> SheetJS 0.20.3 from cdn.sheetjs.com (npm copy frozen at 0.18.5 with open CVEs)
Security
- 77 open Dependabot alerts -> 0 (verified after rescan)
- npm audit: 0 vulnerabilities in prod and dev
- 29 stale dependabot branches deleted; dependabot.yml added
Tooling
- Makefile with db-up/db-seed/build/package/run/audit targets
- docker-compose MySQL 8.4.11 with healthcheck
- README refreshed; 2020 build log preserved as history; current build log appended
Behavior notes
- java.util.Date now serializes ISO-8601 (Jackson 3 default) instead of epoch millis
- POST /api/product upserts explicitly: native id-honoring insert with fresh-transaction retry on concurrent duplicate races
- Seeding via make db-seed forces utf8mb4
Run
Requires JDK 27 and Docker. Then: make db-up, make package, make run. Serves the Angular bundle and API on http://localhost:8080. Seed with make db-seed plus the documented POSTs from db/mock-test.json and db/product.json.
Bug fixes and security (Oct 7 2026)
- BCrypt password hashing on create, login, and reset, with seed accounts scrubbed to demo personas
- Session tokens carry a random per-login secret, so crafted id and type strings no longer impersonate accounts, and a fresh login rotates the secret
- Password reset demands a real stored security answer, login refuses disabled accounts and flattens the email timing oracle, emails are unique with 409 conflicts
- Admin role enforcement on every mutation, own-id semantics on user and bill reads, bill ownership stamped server-side
- Malformed login and logout bodies answer the guest token instead of 500ing
- Product, category, and type creation persists behind the admin role instead of echoing into nothing
- Empty bill lists return 200, SPA deep links forward to index.html
- Admin product create, edit, and import send real JSON bodies, exports name by interface language
- Auth token header with GET-only retry and a 10s timeout, raw reset bodies, padded local bill dates
- Malformed stored tokens read as guest, non-Latin1 passwords encode correctly
Platform
- MySQL 9.7 LTS (9.7.2 image)
- 119 backend tests with a jacoco 90 percent gate at 100 percent actual coverage
- 94 frontend tests with vitest coverage thresholds enforced at 90 percent
- CI on GitHub Actions publishing self-hosted badges to a badges branch