- New dto/InternalDto.hpp with JsonErrorDto, WsEntityEventDto,
WsPresenceUpdateDto, WsClientMsgDto.
- JsonErrorHandler: now takes a shared ObjectMapper (DI). Body built
via writeToString on JsonErrorDto. Closes the audit's concrete bug
where status.description was embedded raw — a Status with a `"`/`\\`
in the description previously emitted invalid JSON.
- AuthInterceptor: takes an optional ObjectMapper ctor arg (defaults to
a fresh mapper). makeForbidden's `msg` is now serialised via
JsonErrorDto + ObjectMapper, so a `"` in a forbidden-reason no longer
breaks the response envelope.
- Hub: process-wide sharedMapper() with optional setObjectMapper()
override. buildPresenceMsg / notifyBooking / notifyPerson all go
through ObjectMapper-emitted DTOs. User-supplied IDs / property IDs
/ usernames containing `"`/`\\`/control chars are now escaped.
- Listener: jsonStr/jsonInt regex parsers gone. handleMessage parses
inbound frames via ObjectMapper::readFromString into WsClientMsgDto.
Malformed JSON / nested objects / escaped quotes — previously silent
corruption — now produce a clean drop of the frame.
- test/test_json_serialization.cpp: 4 cases pinning the round-trip
behaviour (special chars in usernames, IDs, status.description, and
malformed-input rejection).
Bump to 0.4.0 — ctor signatures changed (additive defaults, but the
behaviour of the JSON envelopes is now governed by ObjectMapper).
Closes#6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>