PROJECT CONTEXT / SYSTEM BRIEF This is a hotel-grade Property Management System (PMS) being rebuilt from scratch. This AGENTS file captures product rules + current codebase state. Tech stack - Spring Boot monolith - Kotlin only - JPA / Hibernate - PostgreSQL - Flyway deps present but disabled (no migrations during dev) - Single API domain api.hoteltrisolaris.in Server specs (current) - CPU: i5-8400 - RAM: 48 GB - GPU: RTX 3060 (used for llama.cpp) Core principles - Server is source of truth; clients send intent. - Ledger-based design: never store totals; append rows only. - Occupancy = RoomStay. Billing = Charge. Payments = Payment. Invoices are derived. - Room availability by room number; toAt=null means occupied. - Room change = close old RoomStay + open new one. - Multi-property: every domain object scoped to property_id. - Users belong to org; access granted per property. Immutable rules - Use Kotlin only; no microservices. - Flyway must remain disabled until schema stabilizes. - Canonical staff roles: ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE. - Booking does not own rooms or money. - Realtime events must be derived, not raw DB changes. - Ask before touching auth or payment logic. =============================================================================== CURRENT CODEBASE UNDERSTANDING (TrisolarisServer) =============================================================================== Repository - Root: /home/androidlover5842/IdeaProjects/TrisolarisServer - Entry: src/main/kotlin/com/android/trisolarisserver/TrisolarisServerApplication.kt - Scheduling enabled (@EnableScheduling) Security/Auth - Firebase Admin auth for every request; Firebase UID required. - /auth/verify and /auth/me. Domain entities - Organization: name, emailAliases, allowedTransportModes. - Property: code, name, addressText, emailAddresses, otaAliases, allowedTransportModes. - AppUser, PropertyUser (roles per property). - RoomType: code/name/occupancy + otaAliases. - Room: roomNumber, floor, hasNfc, active, maintenance, notes. - Booking: status, expected check-in/out, emailAuditPdfUrl, transportMode, transportVehicleNumber. - Guest (org-scoped). - RoomStay. - RoomStayChange (idempotent room move). - IssuedCard (cardId, cardIndex, issuedAt, expiresAt, issuedBy, revokedAt). - PropertyCardCounter (per-property cardIndex counter). - GuestDocument (files + AI-extracted json). - GuestVehicle (org-scoped vehicle numbers). - InboundEmail (audit PDF + raw EML, extracted json, status). - RoomImage (original + thumbnail). Key modules Auth - /auth/verify - /auth/me Organizations / Properties / Users - POST /orgs - GET /orgs/{orgId} - POST /orgs/{orgId}/properties - GET /orgs/{orgId}/properties - PUT /properties/{propertyId} - GET /orgs/{orgId}/users - POST /orgs/{orgId}/users (removed; users created by app) - GET /properties/{propertyId}/users - PUT /properties/{propertyId}/users/{userId}/roles - DELETE /properties/{propertyId}/users/{userId} (ADMIN only) Rooms / inventory - /properties/{propertyId}/rooms - /properties/{propertyId}/rooms/board - /properties/{propertyId}/rooms/board/stream (SSE) - /properties/{propertyId}/rooms/availability - /properties/{propertyId}/rooms/availability-range?from=YYYY-MM-DD&to=YYYY-MM-DD Room types - POST /properties/{propertyId}/room-types - GET /properties/{propertyId}/room-types - PUT /properties/{propertyId}/room-types/{roomTypeId} - DELETE /properties/{propertyId}/room-types/{roomTypeId} Properties / Orgs - Property create/update accepts addressText, otaAliases, emailAddresses, allowedTransportModes. - Org create/get returns emailAliases + allowedTransportModes. Booking flow - /properties/{propertyId}/bookings/{bookingId}/check-in (creates RoomStay rows) - /properties/{propertyId}/bookings/{bookingId}/check-out (closes RoomStay) - /properties/{propertyId}/bookings/{bookingId}/cancel - /properties/{propertyId}/bookings/{bookingId}/no-show - /properties/{propertyId}/bookings/{bookingId}/room-stays (pre-assign RoomStay with date range) - /properties/{propertyId}/room-stays/{roomStayId}/change-room (idempotent via RoomStayChange) Card issuing - /properties/{propertyId}/room-stays/{roomStayId}/cards/prepare -> returns cardIndex + sector0 payload - /properties/{propertyId}/room-stays/{roomStayId}/cards -> store issued card - /properties/{propertyId}/room-stays/{roomStayId}/cards (list) - /properties/{propertyId}/room-stays/cards/{cardId}/revoke (ADMIN only) Guest APIs - /properties/{propertyId}/guests/search?phone=... or ?vehicleNumber=... - /properties/{propertyId}/guests/{guestId}/vehicles (add vehicle) Guest documents - /properties/{propertyId}/guests/{guestId}/documents (upload/list) - /properties/{propertyId}/guests/{guestId}/documents/{documentId}/file - AI extraction with strict system prompt. Room images - /properties/{propertyId}/rooms/{roomId}/images (upload/list) - /properties/{propertyId}/rooms/{roomId}/images/{imageId}/file - Thumbnails generated (320px). Transport modes - /properties/{propertyId}/transport-modes -> returns enabled list (property > org > default all). Inbound email ingestion - IMAP poller (1 min) with enable flag. - Saves audit PDF + raw .eml under /home/androidlover5842/docs/emails. - Property match: To/CC email first; fallback to name/code/address/otaAliases. - AI extracts booking fields; creates/cancels Booking. - /properties/{propertyId}/inbound-emails/{emailId}/file (audit PDF) - POST /properties/{propertyId}/inbound-emails/manual (PDF upload) Realtime - SSE room board events with heartbeat, on room create/update, check-in/out, and room change. AI integration - Base URL per profile: dev=https://ai.hoteltrisolaris.in/v1/chat/completions, prod=http://localhost:8089/v1/chat/completions - LlamaClient uses strict system prompt (no guessing). - Read timeout 5 minutes. Config - storage.documents.root=/home/androidlover5842/docs - storage.emails.root=/home/androidlover5842/docs/emails - storage.rooms.root=/home/androidlover5842/docs/rooms - publicBaseUrl entries for docs/emails/rooms - mail.imap.enabled=false by default Notes / constraints - Users are created by app; API only manages roles. - Admin can assign ADMIN/MANAGER/STAFF/AGENT; Manager can assign STAFF/AGENT. - Agents can only see free rooms.