docs: update changelog for v9.3.0-rc1 release

Backfill key changes from 900 commits since 9.2.0 including
architecture rewrite, game system overhauls, client version
support, and developer tooling. Tag Unreleased as 9.3.0-rc1.
This commit is contained in:
Houmgaor
2026-02-28 19:18:11 +01:00
parent bb16306f91
commit 5106b905de

View File

@@ -7,77 +7,158 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed ## [9.3.0-rc1] - 2026-02-28
- Distribution table: remove unused `data bytea NOT NULL` column that prevented seed data from matching Go code expectations (#169) 900 commits, 860 files changed, ~100,000 lines of new code. The largest Erupe release ever.
### Added ### Added
- API: Standardized JSON error responses (`{"error":"...","message":"..."}`) across all endpoints via `writeError` helper #### Architecture
- API: Auth middleware extracting `Authorization: Bearer <token>` header for v2 routes; legacy body-token auth preserved - Repository pattern: 21 interfaces in `repo_interfaces.go` replace all inline SQL in handlers (`CharacterRepo`, `GuildRepo`, `UserRepo`, `SessionRepo`, `AchievementRepo`, `CafeRepo`, `DistributionRepo`, `DivaRepo`, `EventRepo`, `FestaRepo`, `GachaRepo`, `GoocooRepo`, `HouseRepo`, `MailRepo`, `MercenaryRepo`, `MiscRepo`, `RengokuRepo`, `ScenarioRepo`, `ShopRepo`, `StampRepo`, `TowerRepo`)
- API: `returning` field on characters (true if last login > 90 days ago) and `courses` field on auth data (derived from user rights) - Service layer: 6 services encapsulating multi-step business logic (`GuildService`, `MailService`, `GachaService`, `AchievementService`, `TowerService`, `FestaService`)
- API: `/v2/` route prefix with HTTP method enforcement alongside legacy routes - `ChannelRegistry` interface for cross-channel operations (worldcast, session lookup, mail, disconnect) — channels decoupled for independent operation
- API: `GET /v2/server/status` endpoint returning MezFes schedule, featured weapon, and festa/diva event status - Sign server converted to repository pattern with 3 interfaces (`SignUserRepo`, `SignCharacterRepo`, `SignSessionRepo`)
- API: `APIEventRepo` interface and read-only implementation for feature weapons and events
#### Database & Schema
- Embedded auto-migrating database schema system (`server/migrations/`): the server binary now contains all SQL and runs migrations automatically on startup — no more `pg_restore`, manual patch ordering, or external `schemas/` directory
- Catch-up migration (`0002_catch_up_patches.sql`) for databases with partially-applied patch schemas — idempotent no-op on fresh or fully-patched databases, fills gaps for partial installations - Catch-up migration (`0002_catch_up_patches.sql`) for databases with partially-applied patch schemas — idempotent no-op on fresh or fully-patched databases, fills gaps for partial installations
- Embedded auto-migrating database schema system (`server/migrations/`): the server binary now contains all SQL schemas and runs migrations automatically on startup — no more `pg_restore`, manual patch ordering, or external `schemas/` directory needed - Setup wizard: web-based first-run configuration at `http://localhost:8080` when `config.json` is missing — guides through database connection, schema initialization, and server settings
- Setup wizard: web-based first-run configuration at `http://localhost:8080` when `config.json` is missing — guides users through database connection, schema initialization, and server settings - Seed data embedded and applied automatically on fresh installs (shops, events, gacha, scenarios, etc.)
- CI: Coverage threshold enforcement — fails build if total coverage drops below 50% - Database connection pool configuration
- CI: Release workflow that automatically builds and uploads Linux/Windows binaries to GitHub Releases on tag push
- Monthly guild item claim tracking per character per type (standard/HLC/EXC), with schema migration (`31-monthly-items.sql`) adding claim timestamps to the `stamps` table #### Game Systems
- API: `GET /version` endpoint returning server name and client mode (`{"clientMode":"ZZ","name":"Erupe-CE"}`) - Quest enumeration completely rewritten with quest caching system
- Rework object ID allocation: per-session IDs replace shared map, simplify stage entry notifications - Event quest cycling with database-driven rotation and season/time override
- Better config file handling and structure - Quest stamp card system with retro stamp rewards
- Raviente v3 rework: ID system, semaphore handling, party broadcasting, customizable latency and max players
- Warehouse v2 rewrite with proper serialization across game versions
- Distribution system completely rewritten with proper typing and version support
- Conquest/Earth status: multiple war targets, rewritten handlers, status override options
- Festa bonus categories, trial voting, version-gated info (S6.0, Z2)
- Monthly guild item claim tracking per character per type (standard/HLC/EXC)
- Scenario counter implementation with database-driven defaults
- Campaign structs ported with backwards compatibility
- Trend weapons implementation
- Clan Changing Room support
- Operator accounts and ban system
- NG word filter (ASCII and SJIS)
- Custom command prefixes with help command
#### Client Version Support
- Season 6.0: savedata compatibility, encryption fix, semaphore fix, terminal log fix
- Forward.4F.5: ClientMode support added
- G1G2: save pointers enabled, gacha shop fix, compatibility fixes
- G3G9.1: save pointers verified, DecoMyset response fixes
- < G10: InfoGuild response fix, semaphore backwards compatibility
- PS3: PS3SGN support, PSN account linking, trophy course
- PS Vita: VITASGN support, PSN linking
- Wii U: WIIUSGN support
- 40 client versions supported (S1.0 through ZZ) via `ClientMode` config option
#### API
- `/v2/` route prefix with HTTP method enforcement alongside legacy routes
- `GET /v2/server/status` endpoint returning MezFes schedule, featured weapon, and festa/diva event status
- `DELETE /v2/characters/{id}` route
- `GET /version` endpoint returning server name and client mode
- `GET /health` endpoint with Docker healthchecks
- Auth middleware extracting `Authorization: Bearer <token>` header for v2 routes; legacy body-token auth preserved
- Standardized JSON error responses (`{"error":"...","message":"..."}`) across all endpoints
- `returning` field on characters (true if last login > 90 days ago) and `courses` field on auth data
- `APIEventRepo` interface and read-only implementation for feature weapons and events
- OpenAPI spec at `docs/openapi.yaml`
#### Developer Tooling
- Protocol bot (`cmd/protbot/`): headless MHF client implementing the complete sign → entrance → channel flow for automated testing and protocol debugging
- Packet capture & replay system (`network/pcap/`): transparent recording, filtering, metadata, and standalone replay tool
- Mock repository implementations for all 21 interfaces — handler unit tests without PostgreSQL
- 120+ new test files, coverage pushed from ~7% to 65%+
- CI: GitHub Actions with race detector, coverage threshold (≥50%), `golangci-lint` v2, automated release builds (Linux/Windows)
- CI: Docker CD workflow pushing images to GHCR
#### Logging & Observability
- Standardized `zap` structured logging across all packages (replaced `fmt.Printf`, `log.*`)
- Comprehensive production logging for save operations (warehouse, Koryo points, savedata, Hunter Navi, plate equipment) - Comprehensive production logging for save operations (warehouse, Koryo points, savedata, Hunter Navi, plate equipment)
- Disconnect type tracking (graceful, connection_lost, error) with detailed logging - Disconnect type tracking (graceful, connection_lost, error) with detailed logging
- Session lifecycle logging with duration and metrics tracking - Session lifecycle logging with duration and metrics tracking
- Structured logging with timing metrics for all database save operations - Plate data (transmog) safety net in logout flow
- Plate data (transmog) safety net in logout flow - adds monitoring checkpoint for platedata, platebox, and platemyset persistence
- Unit tests for `handlers_data_paper.go`: 20 tests covering all DataType branches, ACK payload structure, serialization round-trips, and paperGiftData table integrity
### Changed ### Changed
- Schema management consolidated: replaced 4 independent code paths (Docker shell script, setup wizard, test helpers, manual psql) with a single embedded migration runner - Minimum Go version: 1.21 → 1.25
- Setup wizard simplified: 3 schema checkboxes replaced with single "Apply database schema" checkbox - Monolithic `handlers.go` split into ~30 domain-specific files; guild handlers split from 1 file to 10
- Handler registration: replaced `init()` with explicit `buildHandlerTable()` construction
- Eliminated `ErupeConfig` global variable — config passed explicitly throughout
- Schema management consolidated: replaced 4 independent code paths (Docker shell script, setup wizard, test helpers, manual psql) with single embedded migration runner
- Docker simplified: removed schema volume mounts and init script — the server binary handles everything - Docker simplified: removed schema volume mounts and init script — the server binary handles everything
- Test helpers simplified: `ApplyTestSchema` now uses the migration runner instead of `pg_restore` + manual patch application - `config.json` removed from repo; `config.example.json` minimized, `config.reference.json` added with all options
- Updated minimum Go version requirement from 1.23 to 1.25 - Stage map replaced with `sync.Map`-backed `StageMap` implementation
- Improved config handling
- Refactored logout flow to save all data before cleanup (prevents data loss race conditions) - Refactored logout flow to save all data before cleanup (prevents data loss race conditions)
- Unified save operation into single `saveAllCharacterData()` function with proper error handling - Unified save operation into single `saveAllCharacterData()` function with proper error handling
- Removed duplicate save calls in `logoutPlayer()` function - SignV2 server removed — merged into unified API server
- `ByteFrame` read-overflow panic replaced with sticky error pattern (`bf.Err()`)
- `panic()` calls replaced with structured error handling throughout
- 15+ `Unk*` packet fields renamed to meaningful names across the protocol
- `errcheck` lint compliance across entire codebase
### Fixed ### Fixed
- Fixed lobby search returning all reserved players instead of only quest-bound players — `QuestReserved` field now counts only clients in "Qs" (quest) stages, matching retail behavior ([#167](https://github.com/Mezeporta/Erupe/issues/167)) #### Gameplay
- Documented log key off-by-one (RE'd from mhfo-hd.dll ZZ): `putRecord_log`/`putTerminal_log` don't use the key in ZZ, so the server value is unused beyond issuance ([#167](https://github.com/Mezeporta/Erupe/issues/167)) - Fixed lobby search returning all reserved players instead of only quest-bound players — `QuestReserved` now counts only clients in "Qs" stages, matching retail ([#167](https://github.com/Mezeporta/Erupe/issues/167))
- Documented user search padding version boundary (8 vs 40 bytes) with RE findings from ZZ DLL; G2 analysis inconclusive ([#167](https://github.com/Mezeporta/Erupe/issues/167)) - Fixed bookshelf save data pointer being off by 14810 bytes for G1Z2, F4F5, and S6 game versions ([#164](https://github.com/Mezeporta/Erupe/issues/164))
- Fixed bookshelf save data pointer being off by 14810 bytes for G1Z2, F4F5, and S6 game versions — corrected offsets to 103928, 71928, and 23928 respectively ([#164](https://github.com/Mezeporta/Erupe/issues/164)) - Fixed guild alliance application toggle being hardcoded to always-open ([#166](https://github.com/Mezeporta/Erupe/issues/166))
- Fixed guild alliance application toggle being hardcoded to always-open — now persisted in DB and togglable by the parent guild leader via `OperateJoint` Allow/Deny actions ([#166](https://github.com/Mezeporta/Erupe/issues/166)) - Fixed gacha shop not working on G1GG clients due to protocol differences — thanks @Sin365 (#150)
- Fixed gacha shop not working on G1GG clients due to protocol differences in `handleMsgMhfEnumerateShop` when `ShopType` is 1 or 2 — thanks @Sin365 (#150)
- Config file handling and validation
- Fixes 3 critical race condition in handlers_stage.go.
- Fix an issue causing a crash on clans with 0 members.
- Fixed deadlock in zone change causing 60-second timeout when players change zones
- Fixed crash when sending empty packets in QueueSend/QueueSendNonBlocking
- Fixed missing stage transfer packet for empty zones
- Fixed save data corruption check rejecting valid saves due to name encoding mismatches (SJIS/UTF-8) - Fixed save data corruption check rejecting valid saves due to name encoding mismatches (SJIS/UTF-8)
- Fixed incomplete saves during logout - character savedata now persisted even during ungraceful disconnects - Fixed incomplete saves during logout character savedata now persisted even during ungraceful disconnects
- Fixed double-save bug in logout flow that caused unnecessary database operations - Fixed stale transmog/armor appearance shown to other players — user binary cache invalidated on save
- Fixed save operation ordering - now saves data before session cleanup instead of after - Fixed login boost creating hanging connections
- Fixed stale transmog/armor appearance shown to other players - user binary cache now invalidated when plate data is saved - Fixed MezFes tickets not resetting weekly
- Fixed client crash when quest or scenario files are missing - now sends failure ack instead of nil data - Fixed event quests not selectable
- Fixed server crash when Discord relay receives messages with unsupported Shift-JIS characters (emoji, Lenny faces, cuneiform, etc.) - Fixed inflated festa rewards
- Fixed data race in token.RNG global used concurrently across goroutines - Fixed RP inconsistent between clients
- Fixed limited friends & clanmates display
- Fixed house theme corruption on save (#92)
- Fixed Sky Corridor race condition preventing skill data wipe (#85)
- Fixed `CafeDuration` and `AcquireCafeItem` cost for G1G5.2 clients
- Fixed quest mark labelling
- Fixed HunterNavi savedata clipping (last 2 bytes)
#### Stability
- Fixed deadlock in zone change causing 60-second timeout
- Fixed 3 critical race conditions in `handlers_stage.go`
- Fixed data race in `token.RNG` global used concurrently across goroutines
- Fixed JPK decompression data race
- Fixed session lifecycle races in shutdown path
- Fixed concurrent quest cache map write
- Fixed guild RP rollover race
- Fixed crash on clans with 0 members
- Fixed crash when sending empty packets in `QueueSend`/`QueueSendNonBlocking`
- Fixed `LoadDecoMyset` crash with 40+ decoration presets on older versions
- Fixed `WaitStageBinary` handler hanging indefinitely
- Fixed double-save bug in logout flow
- Fixed save operation ordering — data saved before session cleanup instead of after
#### Protocol
- Fixed missing ACK responses across handlers — prevents client softlocks
- Fixed missing stage transfer packet for empty zones
- Fixed client crash when quest or scenario files are missing — sends failure ACK instead of nil data
- Fixed server crash when Discord relay receives unsupported Shift-JIS characters (emoji, Lenny faces, cuneiform, etc.)
### Removed
- Compatibility with Go 1.21
- Old `schemas/` and `bundled-schema/` directories (replaced by embedded migrations)
- `distribution.data` column (unused, prevented seed data from matching Go code expectations) (#169)
- SignV2 server (merged into unified API server)
- Unused `timeserver` module
### Security ### Security
- Bumped golang.org/x/net from 0.33.0 to 0.38.0 - Bumped `golang.org/x/net` from 0.18.0 to 0.38.0
- Bumped golang.org/x/crypto from 0.31.0 to 0.35.0 - Bumped `golang.org/x/crypto` from 0.15.0 to 0.35.0
- Path traversal fix in screenshot API endpoint
## Removed - CodeQL scanning added to CI
- Binary blob size guards on save handlers
- Compatibility with Go 1.21 removed. - Database connection arguments escaped
## [9.2.0] - 2023-04-01 ## [9.2.0] - 2023-04-01