Commit Graph

91 Commits

Author SHA1 Message Date
maaz519 cd1eef0098 feat: member portal Sprint 6 — Seva + multi-signal gamification
- SevaOpportunity + SevaEntry + GamificationEvent models + migration
- GamificationService: multi-signal point table (helpful answer +10, seva +20,
  event +5, FAQ +15, welcome +3, profile +5, business +5), idempotent award via
  unique(userId,type,refId), lifetime + time-decayed "recent" score, leaderboard
- SevaModule: admin CRUD + mark-entry-complete (awards SEVA_COMPLETED points)
- Member endpoints in MyController: GET /my/seva, POST /my/seva/:id/signup|cancel
- PROFILE_COMPLETED auto-awarded on profile update (name+hometown+interest)
- /my/seva page: points hero with per-type breakdown, open opportunities w/ signup,
  leaderboard (respects directoryVisible), my seva history
- Member + admin BFF routes; Seva & Points nav item
- Register GamificationModule + SevaModule; add SEVA_* audit actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:44:43 +05:30
maaz519 a0dc94ce79 feat: member portal Sprint 5 — onboarding portal experience + restore Thread schema
- Redesign onboarding into a 5-step wizard: welcome → phone → consent → code → done
- Progress bar, human-readable consent scopes (INGEST/ARCHIVE/REPLICATE/DISPLAY) with descriptions
- Resend-code action, back navigation, indigo theme matching member portal
- "Done" step introduces portal features (digests, events, privacy) with CTA
- Onboard page shell: rounded card, policy footer
- Restore Thread model + Message.expiresAt/quotedPlatformMsgId/threadId + RAW/DNC statuses to schema.prisma (wiped by prior reset; matches existing add_hybrid_ai_architecture migration) — unblocks ThreadsModule registration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:30:58 +05:30
maaz519 0ffdc362b5 feat: member portal Sprint 4 — Events + RSVP
- Event + EventRsvp models + migration (RsvpStatus enum: GOING/MAYBE/NOT_GOING)
- EventsModule: admin CRUD (create/update/delete/publish) + RSVP list
- GET /my/events + POST /my/events/:id/rsvp in MyController/MyService
- Admin BFF routes: GET/POST /api/admin/events, PATCH/DELETE /api/admin/events/[id]
- Member BFF routes: GET /api/my/events, POST /api/my/events/[id]/rsvp
- /my/events page: upcoming/past split, RSVP button (client component, optimistic)
- Register DigestModule, OrgModule, ThreadsModule, EventsModule in AppModule
- Add EVENT_CREATED/DELETED/UPDATED and DIGEST_SENT to AuditAction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:20:11 +05:30
maaz519 f7922454ca feat: member portal Sprint 3 — profile edit form and privacy center
- PATCH /my/profile API endpoint (displayName, hometown, currentLocation, interests, language, digestPreference, directoryVisible)
- BFF PATCH /api/my/profile route
- ProfileForm client component: interest chips, digest preference, language, directory toggle
- Settings page rewrite: profile edit + privacy center (consent list + opt-out) + session + account delete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:06:20 +05:30
maaz519 bc9fe7c145 feat: member portal Sprint 2 — digest history page and restore Digest/DigestConfig schema models
- Restore Digest + DigestConfig models to schema.prisma (wiped by prior git reset)
- Add Tenant.digestConfig / Tenant.digests relations
- GET /my/digest API endpoint (last 20 digests, truncated summary)
- BFF route /api/my/digest
- /my/digest page: digest cards with date, message count, summary preview
- Add Digest nav item to MemberShell sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:04:31 +05:30
maaz519 a685f8b4d5 feat: add spam detection lane (tower.classify.spam) with content-aware filtering
- Add SpamJobData + sync missing job types (DncJobData, ClassifyJobData, P1JobData, etc.) from dist back to source in @tower/types
- spam-detector.ts: emoji-only, short-greeting, link-only detection + duplicate-hash (1h window)
- spam.queue.ts / spam.processor.ts: BullMQ tower.classify.spam lane
- classify.processor.ts: spam check (Step 0) before rule engine, accepts spamQueue param
- main.ts: wire spamQueue + spamWorker; spam pre-filter before ingestQueue.add
- dnc.processor.ts: labelled reason logging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:00:48 +05:30
maaz519 566690bd04 feat: member portal Sprint 1 — dashboard with MemberShell layout and TowerUser profile fields
- Add avatar, hometown, currentLocation, interests, language, digestPreference, directoryVisible fields to TowerUser
- Migration: 20260617200000_add_tower_user_profile_fields
- GET /my/dashboard API endpoint with stats (groups, messages, consents)
- BFF route /api/my/dashboard
- MemberShell 3-column layout (220px nav + flex-1 main + 280px rail)
- Dashboard page: hero card, stat cards, group list, interests chips
- Sidebar returns null for /my paths (MemberShell owns the nav)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:44:58 +05:30
maaz519 622737fdca feat: add web app pages for org portal, thread viewer, and admin org management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:40:40 +05:30
maaz519 435b0e7806 feat: add API modules for digest scheduling, org admin portal, and thread views
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:40:32 +05:30
maaz519 47f345c4bf feat: add worker queue fabric — classify, dnc, p1, review, digest, thread-resolve, outbox, AI modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:40:28 +05:30
maaz519 6aec093516 feat: add org layer to schema and export OrgAdminJwtPayload, adapter, hash from types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:40:24 +05:30
maaz519 978f7effc0 feat: add prisma migrations for p1/digest models, hybrid AI, outbox, and org layer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:40:20 +05:30
maaz519 4f1df96b34 fix: add retry loop for database connection in entrypoint 2026-06-09 16:50:56 +05:30
maaz519 1b63f62ca0 fix: add retry loop for database connection in entrypoint 2026-06-09 16:47:54 +05:30
maaz519 e66f198785 fix: add retry loop for database connection in entrypoint 2026-06-09 16:41:47 +05:30
maaz519 d6da151d16 fix: add retry loop for database connection in entrypoint 2026-06-09 16:35:27 +05:30
maaz519 50026c8a95 fix: add retry loop for database connection in entrypoint 2026-06-09 16:29:46 +05:30
maaz519 9761564c22 fix: shrink images + fix prisma generate in runner 2026-06-09 16:21:55 +05:30
maaz519 9ac3e29a20 fix: add @prisma/client to root deps for Docker runner 2026-06-09 16:09:29 +05:30
maaz519 c8943e8d88 fix: use turbo build in worker Dockerfile for dependency resolution 2026-06-09 15:56:56 +05:30
maaz519 000a06fa0e fix: add prisma to dependencies for Docker build 2026-06-09 15:51:32 +05:30
maaz519 f9d5749dba added changes 2 2026-06-09 15:45:34 +05:30
maaz519 ff4d0f90e8 added changes 2026-06-09 15:33:21 +05:30
maaz519 249d759e6a good forst commit 2026-06-09 02:02:40 +05:30
maaz519 801c1d7121 fix: create new accounts with DISCONNECTED status so QR displays immediately 2026-05-29 11:57:42 +05:30
maaz519 afff6fdbdf feat: add POST /accounts endpoint to create new WhatsApp account records
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:50:01 +05:30
maaz519 2f88e883b2 feat: add AccountsList with Add Account form; proxy POST /accounts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:49:23 +05:30
maaz519 952a0e9b49 feat: pass JID on connect; extract startAccount() helper; poll 30s for new accounts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:44:54 +05:30
maaz519 e8aaae4188 feat: add Accounts page with QR code display for WhatsApp re-authentication
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:40:48 +05:30
maaz519 759b49159e feat: add Next.js proxy routes for accounts list and QR endpoints 2026-05-29 11:37:48 +05:30
maaz519 1dba77959d feat: add AccountsModule with list and QR endpoints
Implements GET /accounts (list all accounts) and GET /accounts/:id/qr
(returns QR code as base64 data URL) using the qrcode package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:15:42 +05:30
maaz519 02dad1347c feat: thread QR/status callbacks through session pool; persist to DB in main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:08:51 +05:30
maaz519 18edce7552 feat: add onQr/onStatus callbacks to session; auto-restart on loggedOut
Adds OnQrCallback and OnStatusCallback parameters to createWhatsAppSession,
broadcasts QR strings and connection status changes to callers, and clears
session files then restarts automatically when the socket is logged out.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 11:04:39 +05:30
maaz519 43f4133f1d feat: add qrCode field to Account for QR re-auth 2026-05-29 10:58:04 +05:30
maaz519 5d9df64849 fix(api): prevent self-loop routes, map P2003 to 400, forward DELETE error body
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:44:48 +05:30
maaz519 9d1799eab1 fix(api): export GroupSummary interface to fix TS4053 declaration emit error 2026-05-28 01:41:12 +05:30
maaz519 1389a65e18 feat(web): add groups page with RouteManager and route handler proxies
Implements the Groups & Routes admin page with a client-side RouteManager
component (add/delete sync routes via fetch), server-side groups page that
pre-fetches groups/routes from the API, and Next.js Route Handler proxies
for /api/routes (GET, POST) and /api/routes/[id] (DELETE). Adds a custom
jest environment that polyfills Node 18+ native fetch into the jsdom sandbox
so tests can use jest.spyOn(global, 'fetch').

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:37:13 +05:30
maaz519 71e2b0681c test(web): assert approvedAt date is rendered in SearchResults 2026-05-28 01:23:25 +05:30
maaz519 6ae1130585 feat(web): add search page with full-text message search UI 2026-05-28 01:19:23 +05:30
maaz519 f7b3ef5a7c feat(web): add sidebar nav layout and dashboard home page 2026-05-28 01:15:53 +05:30
maaz519 d92476f841 fix(api): use PrismaClientKnownRequestError instanceof, add ConflictException for duplicate routes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:13:05 +05:30
maaz519 6b4920ce41 feat(api): add RoutesModule with GET/POST/DELETE /routes endpoints
Implements RoutesService and RoutesController for SyncRoute CRUD, wires
GroupsModule and RoutesModule into AppModule; 11 new tests, all 31 pass.
2026-05-28 01:07:15 +05:30
maaz519 f4a40b573e fix(api): add clearAllMocks and explicit return type to GroupsModule
- Add jest.clearAllMocks() in beforeEach of both spec files to prevent
  call-history state from leaking between tests as the suites grow
- Define GroupSummary interface and use it as explicit return type for
  GroupsService.list() to satisfy TypeScript strict typing requirements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:00:09 +05:30
maaz519 0e92b24bf0 feat(api): add GroupsModule with GET /groups endpoint
Implements TDD-driven GroupsService and GroupsController with full unit test coverage. GET /groups returns all groups ordered by name, selecting id, name, platform, platformId, isActive, and accountId fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:55:13 +05:30
maaz519 e73d39b798 fix(api): escape filter values, clamp pagination, remove redundant ConfigModule import
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:31:43 +05:30
maaz519 8ad5f737bd feat(api): add SearchModule with GET /search endpoint backed by Meilisearch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:28:13 +05:30
maaz519 6f18433c67 fix(worker): throw on invalid approvedAt in index processor 2026-05-28 00:19:14 +05:30
maaz519 1e421c0073 feat(worker): add index queue and wire Meilisearch indexing after approval
Adds index.queue.ts and index.processor.ts to handle BullMQ indexing jobs,
updates main.ts to create a Meilisearch client, configure the index on startup,
and enqueue index + forward jobs from ApprovalResult after a star reaction.
2026-05-28 00:02:47 +05:30
maaz519 7d905b166e test(worker): assert indexDoc in sync-routes approval test 2026-05-27 23:58:44 +05:30
maaz519 6f71e5aee9 feat(worker): handleStarReaction returns ApprovalResult with indexDoc 2026-05-27 23:56:14 +05:30