Phases & timeline

7 phases, ~7-8 months for 2-3 engineers. Each phase ends with a working, demoable slice. No dead ends, no half-built features.

PhaseScopeEffortExit criteria
0 Foundation Monorepo, API, web, DB, Redis, CI, hosting shipped API /v2/health green, Web renders, repo on GitHub
1 Identity + Property Auth, User/Profile/PropertyOwner, Property/Floor/Room, RLS 6 wks Owner logs in, manages own properties; admin sees all
2 Contracts Contract, ContractItem, ContractRoom, payment schedule, lifecycle 6 wks Owner creates/extends/terminates contracts; expiry SMS fires
3 Billing Unified Invoice, Money type, bill generation worker, basic invoice PDF 8 wks Monthly bill run creates invoices + sends them; PDF downloads
4 Payments + recon + eBarimt QPay, SocialPay, Khan/Golomt/TDB statement import, eBarimt outbox 6 wks Tenant pays via QPay; bank statement auto-reconciles; eBarimt receipt issued
5 Chatbot + reports + files + cuts Gemini, remaining reports, file uploads, community cut 4 wks Owner asks chatbot questions; statement PDF matches v1; tenant uploads ID
6 Decommission v1 Mobile API parity, switch all users, archive SQL Server 4 wks XAF host shut down; SQL Server snapshot archived; v2 is the only system

What ships at the end of each phase (demo-able)

Phase 0 — Foundation (DONE)

Phase 1 — Identity & Property (6 wks)

  1. better-auth setup — Drizzle adapter, email+password, JWT plugin, bearer plugin, organization plugin (org = PropertyOwner), phoneNumber plugin (131344 SMS OTP for tenant signup)
  2. RLS middleware — open transaction per request, SET LOCAL GUCs, policies declared on every domain table
  3. Schema: User, Profile, PropertyOwner, Property, Floor, Room
  4. API: /v2/auth/*, /v2/me, /v2/property-owners, /v2/properties, /v2/properties/{id}/floors, /v2/properties/{id}/rooms
  5. Web: login, signup, profile, property list/detail/edit (admin)
  6. Tests: RLS smoke (owner A cannot see owner B's properties)

Exit: deploy preview lets a real PropertyOwner manage their building inventory.

Phase 2 — Contracts (6 wks)

  1. Schema: Contract, ContractItem, ContractRoom, ContractUtility — single status enum, payment schedule as jsonb column for fixed terms
  2. Transition functionsactivate(), extend(), terminate() with allowed-transition table
  3. API: CRUD + actions POST /v2/contracts/{id}/extend, POST /v2/contracts/{id}/terminate
  4. Web: contract list, detail, create wizard, extend modal, terminate confirm
  5. Worker: contract-expiry-notification BullMQ repeatable job (daily 10:00 Asia/Ulaanbaatar) → SMS via 131344
  6. Backfill from v1 — one-shot script reading SQL Server, writing Postgres

Phase 3 — Billing (8 wks) — biggest phase

  1. Unified Invoice model — collapses Bill / InvoiceBill / Sale / Discount. kind enum, amount BigInt, paid_amount BigInt
  2. BigInt Money helpers already in @spacehub/shared
  3. Bill generation worker — BullMQ repeatable (monthly on day-of-month per property), idempotent by (period, contract_id)
  4. InvoicePackage — batch print + email/SMS dispatch
  5. React-PDF templates for the 3-5 most-used reports (statement, invoice, contract)
  6. API: invoices CRUD + actions, package endpoints
  7. Web: invoice list, detail, period selector, batch generate UI

Phase 4 — Payments + bank recon + eBarimt (6 wks)

  1. QPay client (REST) + webhook handler with signature verification
  2. SocialPay client
  3. Khan Bank statement importer — port Excel parser, validate signature
  4. Golomt OpenBanking client
  5. TDB importer
  6. Statement reconciliation service — fuzzy match (date window + amount tolerance + memo fuzzy), index weak-refs in memory to kill O(N·M) leak
  7. eBarimt 3.0 outbox — Sale insert → outbox row in same tx → worker drains → POST to eBarimt → record receipt id
  8. Web: payment status on invoice, recon queue UI

Phase 5 — Chatbot + reports + files + cuts (4 wks)

  1. Gemini chatbot — Vercel AI SDK + @ai-sdk/google, streaming SSE, persist conversation in Postgres, port 10 function-calling tools
  2. Move chatbot PO whitelist to config flag
  3. Remaining React-PDF templates
  4. File storage — Cloudflare R2 or MinIO, presigned upload pattern, sharp thumbnails for property photos
  5. Cut decision — confirm with stakeholders: drop Post/community features or port minimal version

Phase 6 — Decommission (4 wks)

  1. Mobile API parity check — every endpoint SpacehubApiV2 serves has a /v2/* equivalent
  2. Flutter app cuts over — release new mobile version pointed at v2 API
  3. Switch web traffic — reverse proxy routes everything to Next.js
  4. Stop CDC (if used)
  5. Snapshot + archive SQL Server — kept for 12 months as audit fallback
  6. Shut down XAF Blazor + Automation hosts

Risk buffers