Commit Graph

74 Commits

Author SHA1 Message Date
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 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 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
maaz519 d33b4e40b8 fix: use type-only Baileys import and raw status code to fix Jest ESM issue
Replaces DisconnectReason enum import with type-only WASocket import and
uses 401 directly instead of DisconnectReason.loggedOut. Baileys is an ES
module that cannot be executed in Jest's CommonJS mode, so removing the
value import (keeping only type imports) prevents ts-jest from trying to
execute the module.

Also updated session-pool.test.ts to verify end() is called with the
expected Boom error object instead of undefined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 17:40:24 +05:30
maaz519 06449acd96 fix: pass loggedOut reason in closeAll to prevent reconnect timers after shutdown 2026-05-27 17:38:37 +05:30
maaz519 41aabc4c0d fix: address code quality issues in session pool, approval, and main
- session.ts: add onReconnect callback so reconnected socket replaces stale pool entry
- session-pool.ts: pass onReconnect to update pool on reconnect; add closeAll() to gracefully end WebSocket connections on shutdown
- approval.ts: use approved flag so double-approval race (updateMany count=0) returns null instead of sending duplicate forward jobs
- main.ts: wrap pool.add() in try/catch to continue if one account fails; replace silent groupMap fallback with explicit error log and early return; call pool.closeAll() before BullMQ shutdown to prevent hanging sockets
- Tests: add closeAll() test to session-pool.test.ts; add double-approval race test to approval.test.ts (56 tests total, all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 17:35:52 +05:30
maaz519 9e3ee0cd38 feat(worker): wire multi-account pool, reactions → approval → forward pipeline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 17:28:08 +05:30
maaz519 5ad33fd416 feat(worker): forward queue + processor with 20/min rate limiter 2026-05-27 17:23:08 +05:30
maaz519 57a06bc517 fix(worker): atomic approval via transaction, guard null targetGroup
Wrap message.update + approval.create in a $transaction using updateMany
with a PENDING status guard to prevent duplicate approvals and audit gaps.
Filter out null targetGroup routes to prevent runtime errors on DB inconsistency.
Add TODO comment for multi-platform support and fallback accountId comment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 17:21:17 +05:30