Agentic AI CRM/Production
Multi-tenant real-estate CRM for builders and brokerages: lead capture, kanban deals, tower/floor/unit inventory, cost sheets, bookings, milestone payments with UPI reconciliation, and a token-scoped buyer portal.
Solo build: schema, auth and multi-tenancy, the payment and booking engine, the RAG layer and deployment.
The whole sales lifecycle on a shared schema where every query is scoped by workspaceId: lead → contact → deal → site visit → unit → cost sheet and payment plan → booking → milestone collection → documents → reporting. The AI layer sits on top of that rather than beside it, with next-best-action, call analysis, revenue and collections forecasting, and a workspace-wide /ask grounded in the tenant's own rows and documents.
Isolation that survives a forgotten filter, a payment engine where a webhook can arrive twice, and a RAG layer that must answer from one customer's documents without ever seeing another's.
Isolation is enforced mechanically rather than by review. A tenant-scope guard test scans every tenant-model call site in app/, lib/ and modules/ and fails if one lacks a workspaceId predicate, with exceptions registered alongside a checkable reason; two more tests assert that every tenant read path has a recorded broker-visibility decision and that the broker predicate actually reaches Prisma. Vitest covers units and Playwright covers end-to-end flows.
Query scoping is the only deployed isolation layer. Postgres RLS is enabled and 31 policies are written, but they stay inert until the app moves to a NOBYPASSRLS role, a switch gated by a script that refuses to proceed until its checks pass. Advanced retrieval strategies (HyDE, hierarchical, query expansion) are opt-in and not yet evaluated.
Scoping every query by workspaceId is necessary but not sufficient, and RLS that is merely enabled proves nothing: the app connects as a role that owns every table and carries BYPASSRLS, so policies are skipped whether or not they exist. Until a role that respects RLS is in place, the honest backstop is a test that fails the build on any unscoped query. And embeddings from different providers are not comparable, so switching the embedder has to force a reindex.
Tell me what you're building, the constraints you're working with, and where it breaks. I reply within a day.