- SppassOpenHandler/LookupHandler/CloseHandler implementing the eAmuse
sppass.open/lookup/close xrpc methods (request/response schema
confirmed by tracing the client's psmap-based response parser and by
live testing against a real cabinet build)
- SppassSessionService backs open/lookup/close with a token-keyed
session (url + interval for the cabinet to display/poll, later
card_type/card_id once approved)
- CardlessApi: POST /api/cardless/{token}/approve, letting a signed-in
player's phone approve the pending token using their account's
first registered card
- Cardless frontend pages ([token].vue, scan.vue) and useCardlessAuth
composable driving the approval call
- GetConfig GraphQL query + ConfigQuery resolver so the cardless page
can show which server it's talking to
- Wire ISppassSessionService and the cardless routes into Program.cs;
HandlerService now parses model into a GameModel once per request
instead of re-parsing per handler
- Refactor handler dispatch to use a parsed GameModel instead of raw
model strings (Handler.cs, HandlerService.cs, new GameModel.cs)
- Add a Unity asset-extraction subsystem (Abstractions/Extractors/Unity)
- Add WriteEventLogHandler, XrpcDouble serialization type
- Rename EaCoin*Handler -> *EaCoinHandler for naming consistency
- Add PIN/username update and forgot/reset password flows, with a
console-logging IEmailSender until real email is wired up
- Add a settings page and a theming pass (theme tokens, tailwind config)
- Add plugin nav/route/UI-manifest frontend types