|
2 | 2 |
|
3 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
4 | 4 |
|
5 | | -## Recent Changes (2025-08-15) |
| 5 | +## Recent Changes |
6 | 6 |
|
7 | | -### Migration from proposalsOnchains to proposals query |
8 | | -- **GraphQL Queries Updated**: Migrated from `proposalsOnchains` to new `proposals` query endpoint |
9 | | -- **New Features**: |
10 | | - - Added native `title` field support (no longer extracting from description) |
11 | | - - Simplified response structure (direct array instead of `items` wrapper) |
12 | | -- **API Changes**: |
13 | | - - Query parameters: `where` filters replaced with `status`, `fromDate`, `skip`, `limit` |
14 | | - - Response format: `proposals` returns array directly, not `{ items: [...] }` |
15 | | - - Field `proposalsOnchain` renamed to `proposal` for single queries |
16 | | -- **Removed Fields**: `targets`, `values`, `signatures`, `calldatas` (not used by notification system) |
| 7 | +### Slack OAuth Multi-Workspace Support (2025-09-18) |
| 8 | +- OAuth 2.0 flow implementation in Subscription Server (`/slack/install`, `/slack/oauth/callback`) |
| 9 | +- Workspace token storage with AES-256-CBC encryption in `slack_workspaces` table |
| 10 | +- Dynamic token distribution via RabbitMQ messages (bot_token field) |
| 11 | +- Backward compatible with workspace:user ID format (T_DEFAULT for legacy) |
| 12 | +- See `docs/slack-oauth-setup.md` for configuration guide |
17 | 13 |
|
18 | | -## Repository Overview |
| 14 | +### Slack Integration (2025-09-17) |
| 15 | +- Added Socket Mode support for interactive Slack features in Consumer service |
| 16 | +- New service classes: SlackDAOService, SlackWalletService for command handling |
| 17 | +- Session management using InMemorySessionStorage (consider Redis for production) |
| 18 | +- Slack Block Kit UI implementation for rich interactive messages |
19 | 19 |
|
20 | | -This is an event-driven notification system for DAO governance built with microservices architecture. The system monitors blockchain proposals and delivers notifications via Telegram (with extensibility for other channels). |
| 20 | +### GraphQL Migration (2025-08-15) |
| 21 | +- **IMPORTANT**: Currently reverting some changes - `proposals` query now returns `{ items: [], totalCount }` structure |
| 22 | +- Native `title` field support (no longer extracted from description) |
| 23 | +- Query parameters: `status`, `fromDate`, `skip`, `limit` replaced `where` filters |
| 24 | +- Field `proposalsOnchain` renamed to `proposal` for single queries |
21 | 25 |
|
22 | | -## Architecture |
| 26 | +## Architecture Overview |
23 | 27 |
|
24 | | -The system consists of 4 microservices connected via RabbitMQ: |
| 28 | +Event-driven notification system with 4 microservices connected via RabbitMQ: |
25 | 29 |
|
26 | | -1. **Logic System** - Monitors AntiCapture API for proposal events and triggers notifications |
27 | | -2. **Dispatcher** - Processes events, fetches subscribers, and creates notification messages |
28 | | -3. **Subscription Server** - REST API for managing user preferences and tracking notifications |
29 | | -4. **Consumer** - Telegram bot that delivers notifications and handles user interactions |
| 30 | +1. **Logic System** (`apps/logic-system/`) - Monitors AntiCapture API, triggers events every 30 seconds |
| 31 | +2. **Dispatcher** (`apps/dispatcher/`) - Processes events, fetches subscribers, creates notifications |
| 32 | +3. **Subscription Server** (`apps/subscription-server/`) - REST API for user preferences, PostgreSQL persistence |
| 33 | +4. **Consumer** (`apps/consumers/`) - Delivers notifications via Telegram/Slack bots |
30 | 34 |
|
31 | | -## Key Commands |
| 35 | +## Essential Commands |
32 | 36 |
|
33 | | -### Development |
34 | 37 | ```bash |
35 | | -# Install dependencies (requires pnpm) |
36 | | -pnpm install |
37 | | - |
38 | | -# Start all services with Docker Compose |
39 | | -pnpm dev |
40 | | - |
41 | | -# Build all services |
42 | | -pnpm build |
| 38 | +# Development |
| 39 | +pnpm install # Install all dependencies |
| 40 | +pnpm dev # Start all services with Docker Compose |
| 41 | +pnpm build # Build all services |
| 42 | +pnpm test # Run all tests |
| 43 | + |
| 44 | +# Service-specific shortcuts |
| 45 | +pnpm logic-system <cmd> # Run commands in logic-system |
| 46 | +pnpm dispatcher <cmd> # Run commands in dispatcher |
| 47 | +pnpm subscription-server <cmd> # Run commands in subscription-server |
| 48 | +pnpm consumer <cmd> # Run commands in consumer |
| 49 | + |
| 50 | +# Testing patterns |
| 51 | +pnpm --filter @notification-system/logic-system test |
| 52 | +pnpm --filter @notification-system/integrated-tests test -- --testNamePattern="voting" |
| 53 | +NODE_ENV=test pnpm --filter @notification-system/integrated-tests test |
43 | 54 |
|
44 | | -# Run tests across all services |
45 | | -pnpm test |
| 55 | +# Type checking and linting |
| 56 | +pnpm consumer check-types |
| 57 | +pnpm logic-system lint |
46 | 58 |
|
47 | | -# Format code |
48 | | -pnpm format |
| 59 | +# GraphQL code generation |
| 60 | +pnpm client codegen |
| 61 | +ANTICAPTURE_GRAPHQL_ENDPOINT="https://api-gateway-production-0879.up.railway.app/graphql" pnpm client codegen |
49 | 62 | ``` |
50 | 63 |
|
51 | | -### Service-Specific Commands |
52 | | -```bash |
53 | | -# Run commands for specific services |
54 | | -pnpm logic-system <command> |
55 | | -pnpm dispatcher <command> |
56 | | -pnpm subscription-server <command> |
57 | | -pnpm consumer <command> |
| 64 | +## Message Flow Patterns |
58 | 65 |
|
59 | | -# Example: Run tests for logic-system |
60 | | -pnpm logic-system test |
| 66 | +### Notification Pipeline |
| 67 | +1. Logic System polls AntiCapture API → publishes `TriggerEvent` to RabbitMQ |
| 68 | +2. Dispatcher consumes trigger → fetches subscribers with temporal filtering → publishes notifications |
| 69 | +3. Consumer delivers via Telegram/Slack → tracks delivery in Subscription Server |
61 | 70 |
|
62 | | -# Example: Start a single service in dev mode |
63 | | -pnpm logic-system dev |
64 | | -``` |
| 71 | +### Adding New Trigger Types |
| 72 | +1. Extend base `Trigger` class in `apps/logic-system/src/triggers/` |
| 73 | +2. Implement `fetchData()` and `process()` methods |
| 74 | +3. Register in `App.setupTriggers()` in Logic System |
| 75 | +4. Create handler in `apps/dispatcher/src/trigger-handlers/` |
| 76 | +5. Register handler in `TriggerProcessorService` |
65 | 77 |
|
66 | | -### Testing |
67 | | -```bash |
68 | | -# Run all tests |
69 | | -pnpm test |
| 78 | +## Service Architectures |
70 | 79 |
|
71 | | -# Run tests for a specific service |
72 | | -pnpm --filter @notification-system/logic-system test |
| 80 | +### Consumer Service (Telegram/Slack Bot) |
| 81 | +- **Telegram**: Uses telegraf with session management via telegraf-session-local |
| 82 | +- **Slack**: Uses @slack/bolt with Socket Mode for interactive features |
| 83 | +- **Pattern**: Service classes (TelegramBotService, SlackBotService) implement BotServiceInterface |
| 84 | +- **Session Storage**: InMemorySessionStorage for Slack (needs Redis for production scale) |
73 | 85 |
|
74 | | -# Run a single test file |
75 | | -pnpm --filter @notification-system/logic-system test -- path/to/test.spec.ts |
76 | | -``` |
| 86 | +### Subscription Server API |
| 87 | +- **Framework**: Fastify with Swagger documentation |
| 88 | +- **Database**: PostgreSQL with Knex.js migrations in `db/migrations/` |
| 89 | +- **Deduplication**: Tracks notifications in `user_notifications` table |
| 90 | +- **Temporal Filtering**: Only notifies users subscribed before event timestamp |
77 | 91 |
|
78 | | -## Project Structure |
| 92 | +### Logic System Triggers |
| 93 | +- **Base Class**: `Trigger` abstract class with `fetchData()` and `process()` lifecycle |
| 94 | +- **Polling**: 30-second intervals configured per trigger |
| 95 | +- **State Management**: Tracks last processed items to avoid duplicates |
79 | 96 |
|
80 | | -``` |
81 | | -apps/ |
82 | | -├── logic-system/ # Event monitoring and triggering |
83 | | -├── dispatcher/ # Message processing and routing |
84 | | -├── subscription-server/ # User preference API |
85 | | -├── consumers/ # Telegram bot delivery |
86 | | -└── integrated-tests/ # End-to-end testing |
87 | | -
|
88 | | -packages/ |
89 | | -├── anticapture-client/ # GraphQL client for DAO data |
90 | | -└── rabbitmq-client/ # Shared RabbitMQ utilities |
91 | | -``` |
92 | | - |
93 | | -## Key Technologies |
| 97 | +## Database Schema |
94 | 98 |
|
95 | | -- **Runtime**: Node.js 18+, TypeScript 5.8.2 |
96 | | -- **Frameworks**: Fastify (APIs), Express (legacy) |
97 | | -- **Database**: PostgreSQL with Knex.js migrations |
98 | | -- **Message Queue**: RabbitMQ for service communication |
99 | | -- **Testing**: Jest with ts-jest |
100 | | -- **Build**: Turbo monorepo with pnpm workspaces |
| 99 | +Key tables in Subscription Server: |
| 100 | +- `users`: User profiles with platform-specific IDs (telegram_id, slack_id) |
| 101 | +- `user_dao_subscriptions`: Many-to-many subscriptions with created_at for temporal filtering |
| 102 | +- `user_notifications`: Delivery tracking for deduplication |
| 103 | +- `user_wallets`: Wallet addresses for personalized notifications |
101 | 104 |
|
102 | | -## Message Flow |
| 105 | +## Testing Strategies |
103 | 106 |
|
104 | | -1. Logic System polls AntiCapture API every 30 seconds |
105 | | -2. On new proposals, sends `TriggerEvent` to dispatcher queue |
106 | | -3. Dispatcher fetches relevant subscribers and creates notifications |
107 | | -4. Consumer receives notifications and delivers via Telegram |
108 | | -5. Delivery status tracked in Subscription Server |
| 107 | +### Unit Tests |
| 108 | +- Mock RabbitMQ connections with `jest.mock('@notification-system/rabbitmq-client')` |
| 109 | +- Mock GraphQL responses in `integrated-tests/src/mocks/graphql-mock-setup.ts` |
109 | 110 |
|
110 | | -## Database Schema |
| 111 | +### Integration Tests |
| 112 | +- Test helpers in `integrated-tests/src/helpers/` for each platform |
| 113 | +- Use `waitForMessage()` pattern for async message verification |
| 114 | +- Environment: `NODE_ENV=test` for test database isolation |
111 | 115 |
|
112 | | -The Subscription Server manages: |
113 | | -- `users`: User profiles with Telegram/Discord IDs |
114 | | -- `daos`: DAO registry from AntiCapture |
115 | | -- `user_dao_subscriptions`: Many-to-many subscription relationships |
116 | | -- `user_notifications`: Notification delivery tracking for deduplication |
| 116 | +### End-to-End Tests |
| 117 | +- Full service orchestration tests in `apps/integrated-tests/tests/` |
| 118 | +- Docker Compose setup mimics production environment |
117 | 119 |
|
118 | 120 | ## Environment Configuration |
119 | 121 |
|
120 | | -Each service requires specific environment variables: |
121 | | -- Copy `env.example` to `.env` at project root |
122 | | -- Key variables: `DATABASE_URL`, `RABBITMQ_URL`, `TELEGRAM_BOT_TOKEN` |
123 | | -- AntiCapture API endpoint configuration |
124 | | - |
125 | | -## Testing Strategy |
126 | | - |
127 | | -- Unit tests for business logic in each service |
128 | | -- Integration tests for API endpoints |
129 | | -- End-to-end tests in `integrated-tests` app |
130 | | -- Jest configuration in each service's `jest.config.js` |
| 122 | +Required variables in `.env`: |
| 123 | +``` |
| 124 | +DATABASE_URL=postgresql://user:pass@localhost/dbname |
| 125 | +RABBITMQ_URL=amqp://localhost |
| 126 | +TELEGRAM_BOT_TOKEN=your_bot_token |
| 127 | +SLACK_BOT_TOKEN=xoxb-your-token |
| 128 | +SLACK_APP_TOKEN=xapp-your-app-token # For Socket Mode |
| 129 | +SLACK_SIGNING_SECRET=your-signing-secret |
| 130 | +ANTICAPTURE_GRAPHQL_ENDPOINT=https://api-gateway-production-0879.up.railway.app/graphql |
| 131 | +``` |
131 | 132 |
|
132 | 133 | ## Deployment |
133 | 134 |
|
134 | | -- GitHub Actions workflow in `.github/workflows/` |
135 | | -- Deploys to Railway on push to `dev` or `main` |
136 | | -- Path-based deployment triggers for specific services |
137 | | -- Docker Compose for local development mimics production |
138 | | -======= |
139 | | -## Project Overview |
140 | | - |
141 | | -This is an event-driven notification system for DAO governance built with microservices architecture. The system monitors blockchain data for DAO proposals and delivers real-time notifications to users via Telegram. It uses RabbitMQ for message queuing and PostgreSQL for persistence. |
142 | | - |
143 | | -## Architecture |
144 | | - |
145 | | -The system consists of 4 main microservices: |
146 | | - |
147 | | -1. **Logic System** (`apps/logic-system/`) - Monitors AntiCapture GraphQL API and triggers events |
148 | | -2. **Dispatcher** (`apps/dispatcher/`) - Processes trigger events and coordinates notification delivery |
149 | | -3. **Subscription Server** (`apps/subscription-server/`) - REST API for user preferences and subscription management |
150 | | -4. **Consumer** (`apps/consumers/`) - Telegram bot and notification delivery service |
151 | | - |
152 | | -## Development Commands |
153 | | - |
154 | | -### Root Level Commands |
155 | | -- `pnpm dev` - Start all services with Docker Compose |
156 | | -- `pnpm build` - Build all apps using Turbo |
157 | | -- `pnpm test` - Run tests across all apps |
158 | | -- `pnpm format` - Format code with Prettier |
159 | | - |
160 | | -### Per-Service Commands |
161 | | -Use the filter pattern to run commands in specific services: |
162 | | -- `pnpm --filter @notification-system/logic-system <command>` |
163 | | -- `pnpm --filter @notification-system/dispatcher <command>` |
164 | | -- `pnpm --filter @notification-system/subscription-server <command>` |
165 | | -- `pnpm --filter @notification-system/consumer <command>` |
166 | | - |
167 | | -### Testing and Quality |
168 | | -- **Tests**: Each service uses Jest with TypeScript (`jest.config.js` or `jest.config.ts`) |
169 | | -- **Linting**: Logic system has ESLint configured (`pnpm logic-system lint`) |
170 | | -- **Type Checking**: Consumers service has type checking (`pnpm consumer check-types`) |
171 | | - |
172 | | -## Message Flow Architecture |
173 | | - |
174 | | -1. **Logic System** polls AntiCapture API → sends trigger events to RabbitMQ |
175 | | -2. **Dispatcher** consumes trigger events → fetches subscribers → creates notifications → publishes to Consumer queue |
176 | | -3. **Consumer** delivers notifications via Telegram → tracks delivery status in Subscription Server |
177 | | - |
178 | | -## Key Implementation Patterns |
179 | | - |
180 | | -### Trigger System |
181 | | -New trigger types follow this pattern: |
182 | | -- Extend base `Trigger` class in Logic System |
183 | | -- Implement `fetchData()` and `process()` methods |
184 | | -- Register in Logic System's `App` class |
185 | | -- Create corresponding handler in Dispatcher's trigger handlers |
186 | | -- Register handler in `TriggerProcessorService` |
187 | | - |
188 | | -### RabbitMQ Integration |
189 | | -- Logic System publishes trigger events |
190 | | -- Dispatcher consumes trigger events and publishes notification events |
191 | | -- Consumer consumes notification events for delivery |
192 | | - |
193 | | -### Database Migrations |
194 | | -Subscription Server uses Knex.js for database operations with migrations in `db/migrations/` |
195 | | - |
196 | | -## Technology Stack |
197 | | - |
198 | | -- **Runtime**: Node.js 18+ with pnpm workspaces |
199 | | -- **Build Tool**: Turbo for monorepo builds |
200 | | -- **Messaging**: RabbitMQ with custom client abstractions |
201 | | -- **Database**: PostgreSQL with Knex.js migrations |
202 | | -- **API**: Fastify for REST endpoints |
203 | | -- **GraphQL**: Custom AntiCapture client in packages/ |
204 | | -- **Testing**: Jest with ts-jest preset |
205 | | -- **Containerization**: Docker with multi-service compose |
206 | | - |
207 | | -## Environment Requirements |
208 | | - |
209 | | -Essential environment variables: |
210 | | -- `TELEGRAM_BOT_TOKEN` - Telegram bot authentication |
211 | | -- `ANTICAPTURE_GRAPHQL_ENDPOINT` - DAO data source |
212 | | -- `DATABASE_URL` - PostgreSQL connection |
213 | | -- `RABBITMQ_URL` - Message broker connection |
214 | | - |
215 | | -## Extension Points |
216 | | - |
217 | | -- **New Trigger Types**: Follow the pattern documented in `apps/logic-system/add-trigger-logic.md` |
218 | | -- **Notification Channels**: Add new delivery mechanisms in Consumer service |
219 | | -- **DAO Data Sources**: Extend AntiCapture client or add new data providers |
| 135 | +- GitHub Actions deploys to Railway on push to `dev` or `main` |
| 136 | +- Path-based triggers for selective service deployment |
| 137 | +- Docker Compose configuration in `docker-compose.yml` for local development |
0 commit comments