Add full system audit reports and Telegram Mini App debug handoff
- Three-stream audit (security / logic / performance) with 35+ findings derived from actual source code, each with file:line and remediation - Audit Index cross-references criticals across streams into prioritized fix tiers: immediately / before soft launch / before public launch - Telegram Mini App debug handoff documenting what was implemented and all remaining work items with exact file lists and test commands - Updated architecture, data model, auth API, and registration flow docs to reflect Telegram auth, TON wallet, and email verification additions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,10 +37,17 @@ backend/src/
|
||||
│ ├── file/ # Multer uploads, MIME validation
|
||||
│ ├── marketplace/ # PurchaseRequest, SellerOffer, Template, Shop
|
||||
│ ├── notification/ # Templates, delivery, mark-as-read
|
||||
│ ├── payment/ # Payment orchestration + shkeeper/ subdir
|
||||
│ ├── payment/ # Payment orchestration + provider adapters + ledger
|
||||
│ │ ├── adapters/ # Provider-neutral adapter interface + registry
|
||||
│ │ ├── ledger/ # Internal funds ledger (available / held / releasable)
|
||||
│ │ ├── reconciliation/ # Webhook + status reconciliation per provider
|
||||
│ │ ├── migration/ # Legacy data backfill utilities
|
||||
│ │ ├── observability/ # Logging and incident controls
|
||||
│ │ ├── requestNetwork/ # Request Network pay-in, routes, webhook signature
|
||||
│ │ └── shkeeper/ # SHKeeper API, webhook, payout
|
||||
│ ├── points/ # Loyalty points, levels, redemption
|
||||
│ ├── redis/ # Redis client, cache helpers
|
||||
│ ├── telegram/ # Bot webhook, Mini App session, identity linking, notifications
|
||||
│ ├── user/ # Profile, preferences, addresses
|
||||
│ ├── admin/ # Admin-only operations
|
||||
│ └── email/ # Nodemailer transport + templates
|
||||
@@ -98,8 +105,8 @@ The bootstrap is intentionally linear and easy to audit. Execution order:
|
||||
| 10 | `notFound` | tail | Returns 404 envelope for unmatched routes. |
|
||||
| 11 | `errorHandler` | tail | Catches thrown errors, formats response. |
|
||||
|
||||
> [!warning]
|
||||
> Rate-limit middleware is **disabled by default for personal use** (see `app.ts:227` cited in the architecture review). Enable before any real public traffic — `express-rate-limit` is already a dependency.
|
||||
> [!note]
|
||||
> Rate-limit middleware is **active** as of 2026-05-24: auth 10 req/15 min, payment 30/15 min, AI 20/15 min, global 100/15 min. Request Network and Telegram webhooks are exempt from the global limiter. Counters are in-memory — a Redis adapter is planned for distributed deployments.
|
||||
|
||||
---
|
||||
|
||||
@@ -121,7 +128,8 @@ The full route table mounted by `app.ts`:
|
||||
| `/api/payment/decentralized` | `services/payment/decentralizedPaymentRoutes.ts` | mixed | Web3 save, verify, receiver |
|
||||
| `/api/payment/shkeeper` | `services/payment/shkeeper/shkeeperRoutes.ts` | mixed | Intents, webhook, release, refund, config |
|
||||
| `/api/payment/shkeeper/payout` | `services/payment/shkeeper/shkeeperPayoutRoutes.ts` | JWT (seller/admin) | Withdraw to wallet |
|
||||
| `/api/payment/request-network` | `services/payment/requestNetwork/requestNetworkRoutes.ts` | HMAC | Request Network webhooks |
|
||||
| `/api/payment/request-network` | `services/payment/requestNetwork/requestNetworkRoutes.ts` | HMAC sig | Request Network pay-in creation, Secure Payment Page, webhooks |
|
||||
| `/api/telegram` | `services/telegram/telegramRoutes.ts` | mixed (some JWT, webhook uses secret-token) | Mini App verify/session, identity link/unlink, bot webhook |
|
||||
| `/api/chat` | `services/chat/chatRoutes.ts` | JWT | Conversations, messages |
|
||||
| `/api/notification` | `services/notification/notificationRoutes.ts` + `notificationControllerRouter` | JWT | List, mark read |
|
||||
| `/api/dispute` | `services/dispute/disputeRoutes.ts` | JWT | **Not implemented** — planned |
|
||||
@@ -175,15 +183,19 @@ flowchart TB
|
||||
file[file]
|
||||
email[email]
|
||||
socket[socket]
|
||||
telegram[telegram]
|
||||
|
||||
auth --> user
|
||||
auth --> notify
|
||||
auth --> telegram
|
||||
market --> notify
|
||||
market --> chat
|
||||
market --> file
|
||||
pay --> market
|
||||
pay --> notify
|
||||
pay --> socket
|
||||
telegram --> notify
|
||||
telegram --> auth
|
||||
dispute -.-> market
|
||||
dispute -.-> chat
|
||||
dispute -.-> notify
|
||||
|
||||
@@ -17,17 +17,20 @@ How identity, authorization, transport, and integrity are handled across the pla
|
||||
|
||||
| Threat | Mitigation |
|
||||
|---|---|
|
||||
| Credential stuffing | bcrypt 12-round hashing + account lockout + rate-limit (when enabled) |
|
||||
| Credential stuffing | bcrypt 12-round hashing + account lockout + rate-limit |
|
||||
| Session hijacking | Short-lived JWTs (7d), opaque refresh tokens (30d), token rotation |
|
||||
| CSRF | JWT in `Authorization` header (not cookie), CORS allow-list |
|
||||
| XSS | Helmet CSP, React auto-escaping, sanitize HTML before storage |
|
||||
| SQL/NoSQL injection | Mongoose parameterized queries, no `$where` strings, schema validation |
|
||||
| Webhook spoofing | HMAC SHA-256 over body + secret, constant-time compare |
|
||||
| Webhook spoofing | HMAC SHA-256 over body + secret (SHKeeper, Request Network, Telegram), constant-time compare |
|
||||
| File upload abuse | Multer MIME validation, 5 MB cap, non-executable storage, served by Nginx not Node |
|
||||
| Replay attacks | Per-payment idempotency on `providerPaymentId`, per-request `X-Request-Id` |
|
||||
| Replay attacks | Per-payment idempotency on `providerPaymentId`; Telegram initData in-memory replay map; per-request `X-Request-Id` |
|
||||
| Account takeover | Email verification required, password reset code expiry (1h), passkey support |
|
||||
| Phishing | Passkey origin binding (`NEXT_PUBLIC_PASSKEY_ORIGIN`), email domain pinning |
|
||||
| Data leakage | Role-gated endpoints, field-level projection (`select: false` on password), redacted logs |
|
||||
| Forged Telegram identity | `initData` HMAC-SHA256 verified server-side; `initDataUnsafe` never trusted; auth_date max-age enforced |
|
||||
| Telegram callback replay | In-memory replay map with configurable window in `telegramService.ts` |
|
||||
| Blocked Telegram user bypass | `TelegramLink.status === 'blocked'` returns 403 regardless of unlink/re-link attempts |
|
||||
|
||||
---
|
||||
|
||||
@@ -79,7 +82,38 @@ sequenceDiagram
|
||||
> [!warning]
|
||||
> Dev env files ship `NEXT_PUBLIC_PASSKEY_RP_ID=localhost`. In production this MUST be the actual eTLD+1 domain (e.g., `amn.gg`) — passkeys are scoped to the RP ID and can't be transferred.
|
||||
|
||||
### 2.4 Refresh-token rotation
|
||||
### 2.4 Telegram (first-class auth provider)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as User (Telegram)
|
||||
participant FE as Frontend / Mini App
|
||||
participant BE as Backend
|
||||
participant DB as MongoDB
|
||||
U->>FE: opens Mini App (initData available) or clicks Login Widget
|
||||
FE->>BE: POST /api/auth/telegram { initData | loginWidget }
|
||||
BE->>BE: verifyMiniAppInitData() or verifyTelegramLoginWidget()
|
||||
BE->>BE: reject if auth_date stale / replay / bot account
|
||||
BE->>DB: TelegramLink.findOne({ telegramUserId })
|
||||
alt link exists and active
|
||||
BE->>DB: load linked User
|
||||
else no link — auto-provision
|
||||
BE->>DB: User.create({ authProvider:"telegram", telegramVerified:true, email:null })
|
||||
BE->>DB: TelegramLink.create(...)
|
||||
end
|
||||
BE->>DB: upsert TelegramLink.lastSeenAt
|
||||
BE->>BE: generateToken() + generateRefreshToken()
|
||||
BE-->>FE: 200 { user, tokens, isNewUser }
|
||||
```
|
||||
|
||||
- Backend source: `backend/src/services/auth/authController.ts` (`telegramAuth`) and `backend/src/services/telegram/telegramService.ts`.
|
||||
- Mini App path uses `HMAC-SHA256("WebAppData", BOT_TOKEN)` per Telegram spec; Login Widget path uses `HMAC-SHA256(data_check_string, SHA256(BOT_TOKEN))`.
|
||||
- In-memory replay maps guard against duplicate `initData` submissions within a configurable window.
|
||||
- Blocked `TelegramLink` records return `403` — users cannot circumvent by unlinking and re-linking.
|
||||
- Users with `authProvider: "telegram"` have nullable email; email-based operations (password reset) are not applicable to them.
|
||||
- See [[Authentication Flow#Telegram first-class auth flow]].
|
||||
|
||||
### 2.5 Refresh-token rotation
|
||||
|
||||
- On `POST /api/auth/refresh`, the backend:
|
||||
- Verifies the supplied refresh token.
|
||||
@@ -119,7 +153,9 @@ A single User may be `buyer` and `seller` simultaneously (combined role).
|
||||
|
||||
---
|
||||
|
||||
## 5. Webhook integrity (SHKeeper)
|
||||
## 5. Webhook integrity
|
||||
|
||||
### 5.1 SHKeeper
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
@@ -136,11 +172,26 @@ sequenceDiagram
|
||||
end
|
||||
```
|
||||
|
||||
- Body must be the raw bytes used for HMAC — apply `express.raw({ type: 'application/json' })` on the webhook route ONLY (the rest of the app uses parsed JSON).
|
||||
- Raw body must be used for HMAC — `express.raw({ type: 'application/json' })` is mounted on this route only (before the global `express.json()` parser).
|
||||
- In dev (`NODE_ENV === 'development'`) signature verification can be bypassed for local testing — confirm this is gated and never reachable in prod.
|
||||
- Idempotency: identical webhook delivered twice should be no-op. Check by `(providerPaymentId, status)` tuple before mutating.
|
||||
|
||||
See [[Payment Flow - SHKeeper]] for the full flow.
|
||||
### 5.2 Request Network
|
||||
|
||||
- Webhooks arrive at `/api/payment/request-network/webhook` with an `x-request-network-signature` header.
|
||||
- The backend verifies the signature using `backend/src/services/payment/requestNetwork/signature.ts` before any state mutation.
|
||||
- The route is mounted **before** the global `express.json()` body parser so raw body bytes are available for signature computation.
|
||||
- The global rate-limit middleware is configured to skip this path to avoid blocking high-frequency payment events.
|
||||
- Reconciliation service (`requestNetworkReconciliationService.ts`) handles replayed or out-of-order webhooks idempotently.
|
||||
|
||||
### 5.3 Telegram Bot webhook
|
||||
|
||||
- Webhooks arrive at `/api/telegram/webhook` with an `x-telegram-bot-api-secret-token` header.
|
||||
- The backend verifies the token with `verifyTelegramWebhookSecret()` (`telegramService.ts`) before processing updates.
|
||||
- A per-update-id in-memory replay map prevents duplicate processing within the configured window.
|
||||
- The global rate-limit middleware is configured to skip this path.
|
||||
|
||||
See [[Payment Flow - SHKeeper]] for the SHKeeper full flow.
|
||||
|
||||
---
|
||||
|
||||
@@ -224,7 +275,7 @@ The codebase currently uses `morgan` (HTTP access logs) and ad-hoc `logger.info/
|
||||
|
||||
## Related
|
||||
|
||||
- [[Authentication Flow]] · [[Google OAuth Flow]] · [[Passkey (WebAuthn) Flow]] · [[Password Reset Flow]]
|
||||
- [[Authentication Flow]] (includes Telegram first-class auth flow) · [[Google OAuth Flow]] · [[Passkey (WebAuthn) Flow]] · [[Password Reset Flow]]
|
||||
- [[Backend Architecture]] · [[Frontend Architecture]] · [[Real-time Layer]]
|
||||
- [[Payment Flow - SHKeeper]] — webhook HMAC details
|
||||
- [[Environment Variables]] — secret catalog
|
||||
|
||||
Reference in New Issue
Block a user