Development Roadmap
Project: PTX Channel Manager (ptx-cm)
Current Version: 3.0.5
Last Updated: 2026-06-05
Project Phases
Phase 01: Anti-Overbooking Core
Status: ⚠️ PARTIAL (infrastructure complete, OTA integration stubbed)
Priority: P1
Timeline: Original (MVP)
Last Updated: 2026-02-18
Features Delivered:
- [x] OTA Account Management (FR-01) - Encrypted credential storage, session tracking. ⚠️ testConnection/refreshSession are stubs.
- [ ] Property Discovery & Import (FR-02) - ❌ OTA adapters are stubs. No auto-discover, no import UI.
- [x] Booking Pull (FR-03) - BullMQ orchestration + dedup. ⚠️ OTA
fetchBookings()returns empty. No incremental pull. - [x] Availability Auto-Sync (FR-04) - Recalculate logic + overbooking detection. ⚠️ OTA
pushAvailability()is a stub. - [x] Property & Room Management (FR-05) - CRUD for properties, room types, mappings
- [x] Sync Status Dashboard (FR-06) - Real-time overview per property/OTA
- [x] Overbooking Alert (FR-07) - Alert creation/resolve ✅. ⚠️ LINE Notify stub. Email depends on SMTP config.
- [x] Country-Scoped Access (FR-08) - Staff scoped to country, manager sees all
Deliverables:
- Database schema (15 tables)
- NestJS backend with 10 core modules
- Next.js frontend with 6 pages (login, dashboard, properties, bookings, alerts, sync-jobs)
- OTA adapters (Booking.com, Trip.com, Expedia, Agoda Hotel/Homes) — ALL PULL ADAPTERS ARE STUBS (no real HTTP/scraping)
- BullMQ job queue for async sync (orchestration wired, adapters empty)
Known Gaps:
- All 5 OTA pull adapters return empty/false — sync engine runs but produces no real data (Trip.com inbound push is live as of v3.0.5)
/ota-accounts/[id]detail page → 404 (list links to non-existent route)- Import Properties (S-07) screen not built
- No Force Sync button in sync-jobs UI (backend endpoint exists)
- OtaConnection + OtaRoomMapping not seeded
Phase 02: Operational Efficiency
Status: ❌ NOT IMPLEMENTED
Priority: P2
Timeline: Post-MVP
Last Updated: 2026-02-18
Features NOT Built:
- [x] Bulk Rate Update (FR-09) - ✅ bulk-rates module with 4 endpoints (preview, update-base-rate, create-rules, create-plans). Frontend at
/rates/bulk-opsand/rates/bulk-applysub-routes. - [ ] Availability Calendar (FR-10) - ❌ No route, no component, no page.
- [ ] Booking Timeline (FR-11) - ❌ No route, no component, no page.
- [ ] Cancellation Sync (FR-12) - ❌ No cancelBooking in adapter interface. Status workflow can mark cancelled but no OTA-side detection.
Status by Subfeature:
- FR-09: Design ✅ | Implementation ✅ | Testing ❌
- FR-10: Design ✅ | Implementation ❌ | Testing ❌
- FR-11: Design ✅ | Implementation ❌ | Testing ❌
- FR-12: Design ✅ | Implementation ❌ | Testing ❌
Phase 2.5: User Profile & Auth Improvements
Status: ✅ COMPLETE (as of 2026-02-13)
Priority: P2
Timeline: Mid-cycle enhancement
Features Delivered:
- [x] User Profile Management (FR-16) - Edit name, email, locale
- [x] Password Change (FR-17) - Secure password update with verification
- [x] Auth Hydration (FR-18) - GET /users/me on app mount
- [x] Client-Side Theme (FR-19) - Dark/light toggle with localStorage
- [x] Admin Password Reset (FR-20) - Temp password & email reset link flows
- [x] Forgot Password (FR-21) - Self-service password reset
Deliverables:
/profilepage with edit form- Password change modal with mustChangePassword flow
GET /users/meendpoint for auth restoration- Theme toggle in TopBar
- Public pages: /forgot-password, /reset-password, /change-password
- Admin endpoints: POST /users/:id/reset-password, POST /users/:id/send-reset-link
- Public endpoints: POST /auth/forgot-password, POST /auth/reset-password
- PasswordResetToken model with SHA-256 hashing
- Email service integration (HTML reset emails)
- Daily cron job for token cleanup
Implementation Details:
- Profile form: zod validation on frontend, class-validator on backend
- Password change: Current password verification, 8-char minimum, mustChangePassword support
- Auth hydration: Called on app mount, 401 → redirect to login
- Theme: Stored in localStorage, no backend persistence
- Password reset: SHA-256 token hashing, 1-hour expiry, one-time use
- Rate limiting: 3 tokens per user per hour, throttle on endpoints
- Email enumeration prevention: Always return success on forgot-password
- Superadmin hierarchy enforcement: Cannot reset SA password
- Session invalidation: All refresh tokens revoked on password reset
Phase 2.12: Customer Management
Status: ✅ COMPLETE (as of 2026-02-25)
Priority: P2
Timeline: Recent enhancement
Features Delivered:
- [x] Customer Management (FR-33) - Guest profiles with contact info
- [x] Booking Linking (FR-34) - Link/unlink bookings to customers
- [x] Customer Merge (FR-35) - Consolidate duplicate customer records
- [x] Booking History (FR-36) - View all linked bookings per customer
- [x] Fuzzy Suggestions (FR-37) - Smart matching for unlinked bookings
Deliverables:
/customerslist page with search, pagination, status filter/customers/[id]detail page with booking history timeline- Customer CRUD form modal (create/edit)
- Link booking modal with search & suggestions
- Merge customer modal with confirmation
GET /customers,POST /customers,PATCH /customers/:id,DELETE /customers/:idPOST /customers/:id/link,POST /customers/:id/unlink,POST /customers/:id/mergeGET /customers/suggestions- fuzzy match unlinked bookingscustomerstable with indexes on name, email, isActivebookings.customerIdFK (nullable, gradual adoption)- Sidebar nav item "Customers" with Contact icon
- i18n keys for en, vi locales
Implementation Details:
- Soft-delete via isActive flag
- Nullable FK in Booking allows unlinked bookings
- Atomic merge transaction: transfer bookings, soft-delete source
- Pagination helper with cursor support
- Permission checks: VIEW/CREATE/EDIT/DELETE per role
- Last stay enrichment (pulls last check-in from linked bookings)
Phase 2.14: List Page Layout Standardization
Status: ✅ COMPLETE (as of 2026-03-02)
Priority: P2
Timeline: Recent enhancement
Features Delivered:
- [x] Unified List Page Layout (FR-43) - All 4 list pages standardized to bookings-style 4-zone layout
Deliverables:
FilterChipcomponent (components/ui/filter-chip.tsx) — removable filter tagResizableHeadercomponent (components/ui/resizable-header.tsx) — drag-to-resize columns- Bookings (S-08): reference implementation with checkbox column
- Properties (S-03): ResizableHeader columns, status filter
- Suppliers (S-21): ResizableHeader columns, status filter
- Customers (S-26): status filter, no checkboxes/resizable headers
- All pages: fixed h-14 header bar, filter bar with FilterChip + Clear All, sticky uppercase table headers (text-[10px]), compact row padding (px-3 py-1.5), full pagination footer with rows selector + page numbers
Implementation Details:
- 4-zone layout: header bar → filter bar → scrollable table → pagination footer
- Debounced search (300ms) on all pages
- Page reset on filter/search change
- Selected rows cleared on filter/search change (bookings)
- Dark mode support with
dark:variants - Country scope auto-applied from top bar
Phase 03: Security Hardening Sprint
Status: ✅ COMPLETE (as of 2026-02-12)
Priority: P1 (Security)
Timeline: Continuous security improvements
Implemented Phases:
Phase 03.0: Activity Logging (Feb 12)
- [x] NestJS middleware for HTTP request logging
- [x] Efficient tail-reading for large log files (64KB buffer)
- [x] SuperAdminGuard protecting activity logs endpoint
- [x] Activity log dashboard panel with SWR polling
- [x] Environment variable toggle (ACTIVITY_LOG_ENABLED)
Code Changes:
apps/api/src/common/middleware/activity-log.middleware.ts- New middleware logging all requestsapps/api/src/modules/activity-logs/- New module with controller & serviceapps/api/src/common/guards/super-admin.guard.ts- New guard for activity logs endpointapps/web/components/dashboard/activity-log-panel.tsx- Terminal-style activity viewerlogs/added to.gitignore(log files excluded from version control).env.example- AddedACTIVITY_LOG_ENABLED=true
Features:
- Log format:
TIMESTAMP | EMAIL | METHOD | PATH | STATUS | SCREEN - Excludes activity-logs endpoint itself from logging
- Color-coded HTTP method badges (GET/POST/PATCH/PUT/DELETE)
- Status highlighting (2xx/3xx white, 4xx amber, 5xx red)
- SWR polling every 5s with pause/resume controls
- Limit selector (1-500 entries, default 100)
- Terminal-style dark panel on dashboard (super admin only)
Phase 03.1: Auth Hardening (Feb 10)
- [x] DB-backed refresh tokens (RefreshToken model)
- [x] Token rotation on each refresh
- [x] Token revocation on logout & password change
- [x] JWT ID (jti) tracking for session management
- [x] Rate limiting: 5/min login, 10/min refresh
- [x] HttpOnly cookies for token storage
Code Changes:
packages/database/prisma/schema.prisma- Added RefreshToken modelapps/api/src/modules/auth/auth.service.ts- Token storage & revocationapps/api/src/modules/auth/auth.controller.ts- Cookie-based token handling.env.example- JWT_REFRESH_SECRET added
Phase 03.2: Access Control (Feb 11)
- [x] Country-scope guard & decorator
- [x]
assertPropertyAccess()helper - [x]
@Roles(manager)guards on mutations - [x] Allowed countries validation (TH, VN, ID)
- [x] sortBy whitelist on list DTOs
Code Changes:
apps/api/src/common/guards/country-scope.guard.ts- New guardapps/api/src/common/decorators/country-scope.decorator.ts- New decoratorapps/api/src/common/helpers/country-scope.helper.ts- assertPropertyAccess helper- All list DTOs updated with sortBy validation
Phase 03.3: Frontend Security (Feb 11)
- [x] Edge middleware for route protection
- [x] Promise-based token refresh queue (race condition fix)
- [x] Content-Type header forwarding in proxy
- [x] Cookie-only token flow
Code Changes:
apps/web/middleware.ts- Route protection, redirect to /loginapps/web/lib/api-client.ts- Token refresh queue, interceptorsapps/web/app/api/[...proxy]/route.ts- Proxy with header forwarding
Phase 03.4: Infrastructure Security (Feb 12)
- [x] Docker ports bound to 127.0.0.1 only
- [x] Redis password authentication
- [x] ENCRYPTION_KEY placeholder in .env.example
Code Changes:
docker-compose.yml- Port bindings to 127.0.0.1.env.example- ENCRYPTION_KEY documentation
Security Audit Results:
- ✅ No plaintext credentials in code
- ✅ All tokens HttpOnly + SameSite=lax
- ✅ Rate limiting on auth endpoints
- ✅ Country scope enforced on all queries
- ✅ Property ownership verified
- ✅ Role-based access control active
- ✅ Database connections localhost-only
- ✅ Activity logging for admin audit trail
- ✅ SuperAdminGuard protecting sensitive endpoints
Phase 03.5: Workflow & Health System
Status: ✅ COMPLETE
Priority: P1
Timeline: Mar 2026
Features Delivered:
- [x] BPM Workflow Engine
- [x] Unified 4-Axis Booking Status Pipeline
- [x] Visual Workflow Designer
- [x] Booking Health Flags System
- [x] Booking Timeline Sync
Phase 03.7: Lead/Manager Permission Layer
Status: ✅ COMPLETE (2026-04-30)
Priority: P2
Timeline: Apr 2026
Plan: plans/260430-1658-lead-manager-role-override/
Features Delivered:
- [x] Tier-driven permission helpers (
LeadHelpers) — DIRECTOR auto-inherits MANAGER - [x] Override-assignee + Backup-tag participant grants on threads (LEAD+)
- [x] Booking Risk model + lifecycle (flag, category, finalDecision MANAGER+ only)
- [x] Rescue-thread for cancelled bookings (CS LEAD+)
- [x]
/threads/managedpage with department-function tabs (CS, Source, Accounting, GO, OTA, Operations) - [x]
/threads/riskpage (Operations LEAD+ only) - [x] Audit log auto-coverage on all privileged writes
- [x] War-room → threads consolidation (backend + frontend)
Constraints honored: zero changes to 4 booking status fields; no new bits on Role.permissions; identity uses existing CompanyTier.code ladder (STAFF/LEAD/MANAGER/DIRECTOR).
Phase 04: Intelligence & Analytics (Future)
Status: 🔄 PLANNED
Priority: P3
Estimated Timeline: Q2 2026
Features:
- [ ] FR-13: Rate Parity Checker - Compare rates across OTAs
- [ ] FR-14: Revenue Analytics - Revenue by OTA/property/country, occupancy trends, ADR
- [ ] FR-15: Rate Rules Engine - Auto-apply markup/discount/seasonal rules
Acceptance Criteria:
- Rate parity report shows discrepancies with thresholds
- Revenue dashboard with date range filters, grouping options
- Rate rules configured per property/OTA with effective date range
- Automatic rate calculation respects rule priority
Technical Approach:
- New
AnalyticsServicewith aggregation queries - RateRulesService for rule application in pricing
- Dashboard page with recharts visualization
Phase 05: Performance & Caching (Future)
Status: 📋 BACKLOG
Priority: P3
Estimated Timeline: Q3 2026
Goals:
- Redis caching for property/booking lists (5-min TTL)
- Query optimization with Prisma select()
- Database index review and optimization
Metrics Target:
- P95 API response time < 200ms (currently ~500ms)
- List endpoints < 100ms
Phase 06: Real-time Updates (Future)
Status: 📋 BACKLOG
Priority: P2
Estimated Timeline: Q3 2026
Features:
- WebSocket for sync status updates
- Real-time alert notifications
- Availability grid auto-refresh
Technology:
- Socket.io or ws library
- RxJS for event streams
- Frontend subscription via useSWRSubscription or custom hook
Phase 3.2: Trip.com CM OpenTravel Inbound Reservation Push
Status: ✅ COMPLETE (as of 2026-06-05)
Priority: P2
Timeline: June 05
Plan: plans/260604-1754-trip-inbound-opentravel-push/
Features Delivered:
- [x] OpenTravel XML Push Endpoint —
POST /api/v1/ota/trip/reservations(Trip.com webhook) - [x] Reservation Handlers — res_new (create), res_modify (update), res_cancel (stub Type=2) dispatchers
- [x] PAN Redaction — Masked PCI-DSS compliance on logs & audit trail
- [x] Durable OtaInboundMessage Log — Raw XML persisted; supports audit + replay
- [x] XML-Only Responses — All outputs served as OTA-spec XML (never JSON)
- [x] Constant-Time Auth — POS signature validation (HMAC-SHA256)
- [x] Simulator Self-Certification — Mock Trip.com XML payloads + runbook at
docs/ota-trip-inbound-reservation.md - [x] Staging Deployment Runbook — Setup, testing, account manager handoff steps
Deliverables:
- Controller:
trip-reservation-inbound.controller.tswith OpenTravel route - Handlers:
handlers/directory (new/modify/cancel/unknown) for each OTA message type - Mappers: XML ↔ Booking domain model converters
- Service:
trip-inbound.service.ts(auth, parsing, handler dispatch) - DB Model:
OtaInboundMessage(raw XML log + echoToken + messageType) - Runbook:
docs/ota-trip-inbound-reservation.md(setup, simulator, account manager steps) - Tests: 23 unit tests + integration scenarios (authentication, parsing, edge cases)
Constraints Honored:
- ✅ HTTP 200 always on valid XML (Trip.com expects immediate ACK, not error states)
- ✅ PAN redacted in all logs (card last 4 only in audit)
- ✅ XML responses only (OTA-spec compliance)
- ✅ Durable message log supports offline reply (idempotency via echoToken)
- ✅ Cancel as Type=2 stub (awaiting OTA spec clarification)
Remaining Operations (Pending User):
- [ ] Trip.com account manager handoff (credentials, webhook URLs, go-live approval)
- [ ] Staging validator sign-off (simulator test matrix)
- [ ] Production webhook cert setup (if required)
Milestone Status
| Milestone | Target | Status | Completion % |
|---|---|---|---|
| MVP (P1) | 2026-01-31 | ⚠️ Partial | ~70% (infra done, OTA adapters all stubs) |
| Operations (P2) | 2026-02-07 | ⚠️ Partial | ~25% (FR-09 done, FR-10/11/12 not built) |
| User Profile (P2.5) | 2026-02-13 | ✅ Complete | 100% |
| Customer Management (P2.12) | 2026-02-25 | ✅ Complete | 100% |
| List Page Layout (P2.14) | 2026-03-02 | ✅ Complete | 100% |
| Security Sprint (P1) | 2026-02-12 | ✅ Complete | 100% |
| Activity Logging (P1) | 2026-02-12 | ✅ Complete | 100% |
| Internal Chat v1 (Phase 03) | 2026-04-15 | ✅ Complete | 100% |
| Internal Chat v1.1 WebSocket (Phase 04) | 2026-04-20 | ✅ Complete | 100% |
| War Room Ops Dashboard (Phase 05) | 2026-04-25 | ✅ Complete | 100% |
| Lead/Manager Permission Layer + Threads (Phase 06) | 2026-05-01 | ✅ Complete | 100% |
| Lark OTA Listings Data Connection (Phase 07) | 2026-06-04 | ✅ Complete | 100% |
| Trip.com OpenTravel Inbound Push (Phase 08) | 2026-06-05 | ✅ Complete | 100% |
| Intelligence (P3) | 2026-05-15 | 🔄 In Planning | 0% |
| Performance (P3) | 2026-06-30 | 📋 Backlog | 0% |
Phase 3.0: Lead/Manager Permission Layer + Threads Consolidation
Status: ✅ COMPLETE (as of 2026-05-01)
Priority: P1
Timeline: Apr 30 - May 01
Features Delivered:
- [x] Lead/Manager Tier Actions — Override assignee, backup-tag, flag risk
- [x] Booking Risk Model — Flag + categorize + track finalDecision (MANAGER+)
- [x] Rescue Threads — CS LEAD+ creates conversation on cancelled bookings
- [x] Threads Consolidation —
/threadsreplaces/war-room; routes under/threads/* - [x] Managed Threads Page — Per-department function scoped (fn-tabs, LEAD+ only)
- [x] Risk Threads Page — OPS-only risk-flagged view with decision tracking
- [x] Tier-Based Navigation —
useDeptTierhook powering UI visibility - [x] Audit Coverage — All privileged writes logged (BookingRisk, Conversation, Participant)
Deliverables:
BookingRiskmodel +RiskCategoryenum (refund_heavy, customer_cancel, many_incidents)Conversationself-relation for rescue-thread linkage- API endpoints:
/threads/list,/threads/unread-count,/threads/managed,/threads/risk,/threads/:id/assignee,/threads/:id/participants/backup,/threads/rescue - Risk endpoints:
GET/POST/PATCH /risks/:bookingId - 22 frontend components (threads module replaces war-room)
- 47 new unit tests
- Env var renamed:
NEXT_PUBLIC_WAR_ROOM_ENABLED→NEXT_PUBLIC_THREADS_ENABLED
Constraints Honored:
- ❌ No changes to 4 booking status fields
- ❌ No new bits on
Role.permissions - ❌ No
isLead/isManagerbooleans — single source of truth =DepartmentMember.companyTier.code - ✅ Auto-assign flow untouched
- ✅ Mandatory check-points (e.g. no check-in without deposit) NOT bypassable
Implementation Details:
- Tier ladder: STAFF < LEAD < MANAGER < DIRECTOR
- LEAD+: Override assignee, backup-tag, flag risk
- MANAGER+: Flag risk + set finalDecision
- DIRECTOR: Inherits MANAGER privileges
- All ops gate behind
LeadHelpersservice auth checks - Audit: All privileged writes logged via prisma-audit extension
Phase 3.1: Lark OTA Listings Data Connection
Status: ✅ COMPLETE (as of 2026-06-04)
Priority: P2
Timeline: June 04
Features Delivered:
- [x] Lark Metadata Model — 25 columns in OtaConnection (otaPropertyName, ptxSync, propertyLink, bank, sourceStatus, otaStatus, etc.)
- [x] Unmapped Listings Support — propertyId nullable; country-scope fallback to otaAccount.countryCode
- [x] Import Pipeline — CSV from Lark Bitable → idempotent upsert (otaAccountId, otaPropertyId key)
- [x] Placeholder OTA Accounts — Auto-create per platform ("X (Lark)" label, expired status)
- [x] Building Matching — cleanName logic for property-building association
- [x] OTA Properties UI — New route
/ota-properties, KPI cards, filter chips, inline-edit grid - [x] Property Detail Mapping Tab — Upgraded to show + link/unlink listings
- [x] Schema Consolidation — All prior db-push drift resolved in migration
20260604165408_supplier_geo_ota_lark_consolidation
Deliverables:
OtaConnectionmodel: + 25 Lark columns; unique key (otaAccountId, otaPropertyId); propertyId nullableSupplierApartmentmodel: Lark-sourced building hierarchy; source ∈- API:
GET /ota-connections(paginated, filters),PATCH /ota-connections/:id(metadata edit),PUT /ota-connections/:id/map(link/unlink),DELETE - Import script:
packages/database/prisma/import_lark_ota_properties.ts; idempotent; report (created/updated/skipped/unmapped) - Helpers:
packages/database/prisma/lark_import_helpers.ts(cleanName, labelResolver) - Frontend:
/ota-propertiespage, components, i18n (en, vi) - Schema migration:
20260604165408_supplier_geo_ota_lark_consolidation(resolves ALL prior drift)
Constraints Honored:
- ✅ Unmapped listings fully queryable and editable (propertyId=NULL, country from otaAccount)
- ✅ Import idempotent on re-run (keyed by otaPropertyId)
- ✅ No changes to booking or sync pipelines
- ✅ Building matching respects existing cleanName logic (supplier apartments baseline)
Data Results:
- First import: 1723 CSV rows → 1712 connections created
- 11 rows skipped (no PROPERTY ID in Lark)
- 174 unmapped (empty building name on Lark; still created with propertyId=NULL)
Phase 3.2: Lark-Style Advanced Filters (Generic DSL)
Status: ✅ COMPLETE (as of 2026-06-04)
Priority: P2
Timeline: June 04
Features Delivered:
- [x] Advanced Filter DSL — Generic
FilterConditioninterface (field, op, value); transport via?af=URL-encoded JSON; max 20 conditions, 50 array values per condition - [x] Filter Registry System — Per-module field whitelisting + operator mapping (1-level relations only);
module-filter-registries.tscentral map (avoids cycles); public metadata viaGET /{module}/filter-fields - [x] Pilot Modules — supplier-apartments + bookings integrated with af support; per-module registry files
- [x] Date Semantics — Fixed business TZ (Asia/Ho_Chi_Minh +07:00); timestamptz day boundaries computed server-side; plain-date fields compare as calendar dates
- [x] Saved Views —
FilterViewPrisma model (id, module, name, filters JSON, isShared, createdBy, company); CRUD endpoints with owner-only mutate (403/404); company-scoped shared visibility - [x] Server-Side Validation — Filters re-validated on apply; field registry drift prevention
- [x] FilterBuilder UI — React components: FilterBuilder button+panel, condition rows (type-switched operators), field picker, entity multi-select, saved views picker
- [x] Integration — Hooks:
useAdvancedFilters(encode/decode),useFilterFields(fetch registry),useFilterViews(CRUD); wired into supplier-apartments + bookings pages; i18nfilters.*(en, vi)
Deliverables:
- Backend:
common/filtering/(DSL types, operators, registries, Prisma builder, param parser);modules/filter-views/(CRUD); registries for supplier-apartments + bookings - Frontend:
components/ui/filter-builder/(all components + hooks) - Database:
FilterViewmodel + migration20260604102334; index on (companyId, module) - API Spec: Endpoints for
/bookings/filter-fields,/supplier-apartments/filter-fields,/filter-viewsCRUD;afparam on list endpoints - Documentation: System architecture section 2f, API spec updates, codebase-summary enhancements
Extension Pattern:
- Create module-level filter registry file (field whitelist + prismaPath)
- Add entry to
module-filter-registries.tsmap - Wire
af?: stringparam into ListXxxDto - Call
applyAdvancedFilters()in service list method - Add
<FilterBuilder module="..." />to frontend list page - (Optional) Custom field picker logic if needed
Constraints Honored:
- ✅ AND semantics only (no OR groups); country scope never clobbered
- ✅ 1-level relations only; no nested field filters
- ✅ Hard limits enforced (20 conditions, 50 array values)
- ✅ Public metadata hides prismaPath (no internal details leaked)
- ✅ Filters re-validated on apply (prevents schema drift)
- ✅ Saved views owner-only mutable; company-scoped read
Coexistence Note:
Bookings legacy localStorage saved views remain (consolidation deferred); new FilterView backend views gradually migrate.
Known Issues & Debt
Code Debt
- [ ] Audit trail not wired to AuditLogInterceptor (minor)
- [ ] OTA adapters use Playwright (fragile, not production-ready for scale)
- [ ] No comprehensive error retry strategy for OTA API calls
- [ ] Rate limiting config hardcoded (should be configurable)
Feature Gaps
- [ ] User invitation/onboarding flow
- [ ] Email templates for notifications
- [ ] Batch user import (CSV)
- [ ] Property bulk operations (enable/disable)
- [ ] Advanced alert filtering & resolution workflows
Performance
- [ ] No caching on frequently accessed queries
- [ ] Large booking lists (1000+) may be slow
- [ ] No DB index on (room_type_id, date, otaType)
Documentation
- [ ] OTA adapter implementation guide
- [ ] Deployment to production (Docker/K8s)
- [ ] Monitoring & alerting setup
- [ ] Disaster recovery procedures
Success Metrics
Q1 2026
- ✅ Zero overbooking incidents (from previous 5-10/week)
- ✅ 60s avg sync latency (target: <60s)
- ✅ 99% uptime during business hours
- ✅ All 4 OTA channels reliably synced
Security (Feb 2026)
- ✅ All auth tokens DB-tracked
- ✅ Country scoping enforced on 100% of queries
- ✅ Rate limiting active on all auth endpoints
- ✅ Zero plaintext credential storage
User Adoption
- ✅ 15 staff accounts active
- ✅ 100+ properties managed
- ✅ <5 min avg time to find/manage booking
Development Rules & Constraints
Team: 1 solo developer
Tech Stack:
- Backend: NestJS 10, Prisma 7, PostgreSQL 16, Redis 7, BullMQ
- Frontend: Next.js 16, React 18, Tailwind CSS, TanStack Table
- Testing: Jest, @nestjs/testing
- Deployment: Docker + docker-compose
Standards:
- All features branch from main, PR required
- Tests must pass before merge (jest + coverage 80%+)
- Code review by: [project owner]
- Commit format: Conventional Commits
- Documentation: Update docs/ on feature merge
Deployment:
- Manual deployments (no CI/CD yet)
- Blue-green strategy (if multi-server)
- Database migrations: Prisma migrate
Next 30 Days (Feb - Mar 2026)
Week 1 (Feb 13-19)
- [x] Complete admin password reset feature (temp password + email link)
- [x] Complete self-service forgot password flow
- [ ] User acceptance testing with ops team
- [ ] Bug fixes from Phase 2.5 testing
Week 2-3 (Feb 19 - Mar 5)
- [ ] Performance profiling & caching analysis
- [ ] Begin Rate Rules engine design
- [ ] Gather user feedback on UI/UX
Week 4 (Mar 5-12)
- [ ] Planning sprint for Phase 04 (Analytics)
- [ ] Infrastructure performance tuning
- [ ] Production deployment if needed
Critical Dependencies
- PostgreSQL 16 database (production backup needed)
- Redis 7 for BullMQ (critical path for async jobs)
- OTA APIs stability (Booking.com, Trip.com, Expedia, Agoda)
- SSL certificates for HTTPS (production)
- SMTP server for email notifications
Communication Plan
- Weekly standup: [to be defined]
- Issue tracking: [GitHub Issues, if applicable]
- Documentation: Updated on each feature merge
- Stakeholder updates: [to be defined]
Related Documentation
- SRD.md - Functional requirements
- API_SPEC.md - API endpoint reference
- DB_DESIGN.md - Database schema
- system-architecture.md - Architecture & security details
- code-standards.md - Development guidelines
- codebase-summary.md - Project structure
Revision History
| Date | Version | Changes |
|---|---|---|
| 2026-06-05 | 3.0.5 | Trip.com OpenTravel Inbound Push COMPLETE: XML endpoint, new/modify/cancel handlers, PAN redaction, durable OtaInboundMessage log, constant-time auth, XML responses only, runbook + simulator (Phase 3.2); Phase 3.1 recap: Lark OTA listings (1712 imported, propertyId nullable); Phase 3.0: Lark-style advanced filters DSL + registry system + saved views |
| 2026-06-04 | 3.0.4 | Entity internal code module COMPLETE: internalCode on 7 entities, EntityCodeService, lib/routes.ts builders, per-entity prefix codes (BK-, MY-, etc.), code-standards checklist |
| 2026-06-04 | 3.0.3 | List pages optimization COMPLETE: usePaginatedList hook, stats/facets endpoints, server-side sort, 5 pages integrated (suppliers, customers, bookings, properties, ota-connections) |
| 2026-06-04 | 3.0.2 | OTA listings compact table + drawer UX phase; Lark CSV import pipeline (1712 rows) |
| 2026-06-04 | 3.0.1 | Lark OTA listings data connection phase 1: OtaConnection metadata (25 columns), unmapped listings support, property detail mapping tab |
| 2026-05-01 | 3.0.0 | Lead/Manager Permission Layer + Threads Consolidation COMPLETE: BookingRisk model, tier-based ops (LEAD+ override/backup-tag, MANAGER+ finalDecision), rescue-threads, /threads replaces /war-room, managed + risk pages, 47 new unit tests, audit coverage |
| 2026-04-25 | 2.9.6 | War Room Ops Dashboard COMPLETE: /war-room route, GET /api/v1/chat/war-room/threads endpoint, 3-pane layout, 4 filter chips, 20s SWR poll + socket invalidation, 13 components, 131 tests (94 frontend + 37 backend) |
| 2026-04-23 | 2.9.5 | Threads on Booking Detail Page COMPLETE: reply UI with thread panel, reply-count footer, 13/13 web tests pass |
| 2026-04-22 | 2.9.4 | Thread Reconciliation + Admin Tools COMPLETE: BullMQ replyCount sync job, admin endpoint, WS payload enrichment, runbooks, chaos tests |
| 2026-04-20 | 2.8.2 | In-App Notifications Follow-ups COMPLETE: per-user preferences, chat mention rows, actor attribution, admin global audience (67 tests pass) |
| 2026-04-20 | 2.7.0 | Internal Chat Phase 04 COMPLETE: WebSocket realtime v1.1 (typing, presence, receipts, backfill); 86/86 tests pass; added to milestone tracking |
| 2026-04-19 | 2.6.0 | Escalation target picker + master data consolidation complete |
| 2026-03-16 | 2.5.0 | FR-09 Bulk Rate implemented: bulk-rates API (4 endpoints), /rates/bulk-ops and /rates/bulk-apply sub-routes, property search/select-all UX |
| 2026-03-02 | 2.4.0 | Added Phase 2.14 List Page Layout Standardization COMPLETE (FR-43: FilterChip, ResizableHeader, 4-zone layout on S-03/S-08/S-21/S-26) |
| 2026-02-25 | 2.3.0 | Updated Phase 2.12 Customer Management to COMPLETE (CRUD, link/unlink/merge, fuzzy suggestions) |
| 2026-02-18 | 2.1.0 | Implementation audit: corrected Phase 01 to PARTIAL (OTA adapters all stubs), Phase 02 to NOT IMPLEMENTED (FR-09/10/11/12 not built), updated milestones |
| 2026-02-13 | 2.2.0 | Added admin password reset (temp password, email link) and self-service forgot password to Phase 2.5 |
| 2026-02-12 | 2.1.0 | Added Phase 03.0 Activity Logging (middleware, API, dashboard panel), SuperAdminGuard |
| 2026-02-12 | 2.0.0 | Added security sprint phases (01-04), Phase 2.5 user profile complete |
| 2026-02-10 | 1.9.0 | Phase 01 MVP + Phase 02 complete |
| 2026-02-01 | 1.0.0 | Initial roadmap (skeleton) |