- Add MessageSource model and message_sources table
- save_messages now stores sources linked to assistant message
- GET /room/{room_id} returns sources per message (empty [] for user role)
- Fix page_label int->str cast to prevent asyncpg DataError
- Orchestrator now receives conversation history for context-aware query rewriting
- Chatbot includes full conversation history for coherent multi-turn responses
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: chat history, room soft-delete, and user migration to PostgreSQL
## Chat History
- Persist user and assistant messages to `chat_messages` table after every
chat interaction (both LLM-generated and direct/greeting responses)
- GET /room/{room_id} now returns full chat history via eager-loaded
`messages` relation, sorted by created_at ascending
- Added `ChatMessageResponse` Pydantic model to room response schema
## Room Soft Delete
- Added `status` column (active | inactive) to Room model
- GET /rooms/{user_id} filters to only return active rooms
- New DELETE /room/{room_id}?user_id=... endpoint: sets status to inactive
instead of physically deleting the row (data preserved for audit/recovery)
- Added idempotent migration in init_db.py:
ALTER TABLE rooms ADD COLUMN IF NOT EXISTS status VARCHAR NOT NULL DEFAULT 'active'
## User Migration: MongoDB → PostgreSQL
- Migrated user storage from MongoDB to PostgreSQL (User model added to models.py)
- get_user() now queries PostgreSQL via AsyncSessionLocal instead of MongoClient
- Replaced all emarcal…