Commit b800342
committed
feat(server): /comp/* companion routes + env-gated /comp/affinity debug
* routes/companion.rs (1230 lines, 9 routes): personas, chat lifecycle
(start/message/message_async/pending/history/sessions), profile,
event/gift, gifts list. All utoipa-annotated.
* routes/debug.rs (env-gated): GET /comp/affinity/{session_id} returns
6-dim vector + ghost stats + relationship_label. Mounted only when
EXPOSE_AFFINITY_DEBUG=true.
* routes/mod.rs: top-level router(state) -> OpenApiRouter<AppState>.
Merge (not nest) to avoid /comp/comp double-prefixing since handler
utoipa::path annotations carry full /comp/... paths. Auth layer
applied to comp+debug subtree only; healthz stays public.
* routes/health.rs: generic over S so it composes into both pre-T12
stateless main and the AppState-backed router.
* Auth: every protected handler reads Extension(AuthUser(user_id))
from the JWT — no user_id in request bodies. Path-user vs JWT-user
mismatch returns 403 (list_sessions, get_profile). Session ownership
verified per route via require_session_for_user helper.
* Gift redesign: collapsed gateway's /tip + /gift into one
/chat/{session_id}/event/gift taking {deltas, label, metadata}. No
ShopItem / credit_wallet imports. Pipeline bypass: route writes the
gift_user message + applies deltas directly via persist_with_event,
because pde::decide returns zero deltas for Event::Gift in core. LLM
reaction emerges on the next user turn.
* 8 new integration tests (sqlx::test + tower::Service::call). 76 tests
pass total (25 core + 12 llm + 19 server + 20 store).
Signed-off-by: enriquephl <70942788+enriquephl@users.noreply.github.com>1 parent 896e768 commit b800342
4 files changed
Lines changed: 1376 additions & 1 deletion
0 commit comments