# Senoa MonoRepo — Project Audit Report

**Date:** 2026-06-29
**Repo:** `SenoaMonoRepo` (branch `development`)
**Scope:** Full monorepo — backend, blockchain indexer, web, admin-panel, infra/CI

---

## 1. Executive Summary

Senoa is a **Web3 social + marketplace platform** built as a Turbo/PNPM monorepo. It comprises a large NestJS backend (42 modules, crypto custody, KYC/KYB, accounting, affiliate/MLM rewards), a Next.js 15 web client, a Vite/React admin panel, and a NestJS blockchain events indexer.

The architecture is reasonable and the code is consistently structured, but the project is **not production-ready**. The dominant themes are:

- **Critically low test coverage** across every app (backend 0.97%, web 0 tests, admin 1 file, blockchain 1 broken test).
- **Security misconfigurations** — wildcard CORS with credentials, JWTs in `localStorage`, a hardcoded Alchemy RPC key, hardcoded DB/JWT secrets in `docker-compose.yml`, default Swagger password, no rate-limiting or security headers.
- **Incomplete financial logic** — reward distribution and price-oracle integration are stubbed with TODOs; non-stablecoin exchange rates are hardcoded to `1.00`.
- **Operational gaps** — blockchain indexer has no reorg handling, no idempotency, and no retries.

**Overall production-readiness: ~70%. Risk level: HIGH.**

---

## 2. Project Structure & Stack

| App | Stack | Files | Tests |
|-----|-------|------:|------:|
| `apps/backend` | NestJS 9, TypeORM, Postgres, Passport/JWT, 124 migrations | 625 | 6 (trivial) |
| `apps/web` | Next.js 15, React 19, thirdweb/viem, TanStack Query, Zustand, socket.io | 280 | 0 |
| `apps/admin-panel` | Vite 7, React 19, CoreUI, Redux Toolkit, RR7 | 62 | 1 |
| `apps/blockchain` | NestJS 9, ethers v5, Bull/Redis, Postgres | 14 | 1 (failing) |
| `packages/*` | shared `eslint-config`, `tsconfig` | — | — |

**Tooling:** Turbo + PNPM 10.15, TypeScript, Tailwind, Docker, AWS Elastic Beanstalk (GitHub Actions deploy).

**Repo-wide metrics:** 37 TODO/FIXME, 264 console.* in TS files, **208 remote branches** (significant branch sprawl).

---

## 3. Critical Findings (fix before any production use)

### C1 — Hardcoded Alchemy RPC API key (committed secret)
`apps/blockchain/src/app.service.ts:31`
```ts
new ethers.providers.JsonRpcProvider(
  `https://polygon-amoy.g.alchemy.com/v2/fBeW2OzQkFjcaNQVXzqx5rDBeO_AwMFO`)
```
Live key in source + git history. **Rotate immediately**, move to `process.env`.

### C2 — Secrets hardcoded in `docker-compose.yml`
DB passwords (`P71\Q4;jlpyJ`, `jRw0hf56E6x'`) and `JWT_SECRET=your-super-secret-jwt-key-change-in-production` are committed. Also `scripts/init.sql` ships `appuser`/`rootpassword`. Move to secrets/`.env` (prod already uses AWS SSM Parameter Store via the EB prebuild hook — good — but compose does not).

### C3 — Wildcard CORS with credentials
`apps/backend/src/main.ts:91-96` and `gateway/chat.gateway.ts` use `origin: "*"` with `credentials: true`. CSRF / cross-origin credential exposure risk. Pin to explicit origins.

### C4 — Near-zero test coverage everywhere
Backend 6 trivial `.spec` files (0.97%), web **0**, admin 1, blockchain 1 (and that e2e test asserts the wrong string, so it fails). No tests on auth, custody, accounting, KYC/KYB, or rewards.

### C5 — Incomplete / incorrect financial logic
- `accounting.service.ts:655,752,877` — non-USDT `exchangeRate` hardcoded to `"1.00"` (TODO: price oracle). All non-stablecoin ledger values are wrong.
- `circle.service.ts:1297-1346` — reward distribution has `TODO: [DB INSERT]` placeholders; rewards are computed but **never recorded**. Users would not be paid.

### C6 — JWT stored in `localStorage` (web + admin)
43 reads in web, plus admin panel. XSS-exfiltratable. Client-side-only token expiry (`token-init-date`) is trivially bypassed. Move to httpOnly cookies; rely on server 401s for expiry.

---

## 4. High-Severity Findings

| # | Area | Finding | Location |
|---|------|---------|----------|
| H1 | Web | XSS via `dangerouslySetInnerHTML` with regex-only sanitization (4 sites) | `ProfilePreview.tsx:70`, `AboutUsEditor.tsx:298`, etc. |
| H2 | Backend | Default Swagger password `swagger@123` fallback | `main.ts:47` |
| H3 | Backend | No rate-limiting (`@nestjs/throttler`) and no security headers (`helmet`) anywhere | global |
| H4 | Backend | S3 uploads use raw filename (collision/overwrite), no virus scan, 24h presigned URLs | `aws.service.ts`, `upload.service.ts` |
| H5 | Backend | Password-reset token stored in plaintext in DB | `auth.service.ts:862` |
| H6 | Backend | Individual KYC is minimal — no workflow, no status, no audit trail (KYB is robust) | `kyc/` |
| H7 | Blockchain | No reorg protection, no block-confirmation wait, no idempotency, `attempts:1` (no retries) → events silently lost/duplicated | `app.service.ts`, `erc20transfer.processor.ts` |
| H8 | Admin | Role checks are client-side only (Redux/localStorage); no CSRF protection | `ProtectedRouteByRole.js` |
| H9 | All | Oversized files: web `settings/page.tsx` (3139), `profile/[id]/page.tsx` (2540); backend `posts.service.ts` (2256), `circle.service.ts` (1911); admin `ContentCreators.js` (930) | — |

---

## 5. Medium / Low Findings

- **Lint disabled** in `web` and `admin-panel` (`"lint": "echo skipped"`); blockchain too. ESLint configs exist but never run.
- **TypeScript strictness off** in admin (`strict:false`, `noUnusedLocals:false`) and blockchain (`strictNullChecks:false`, `noImplicitAny:false`). Web is strict.
- **264 console.* calls** in TS (185 in web, 57 backend) — no structured logging / log-level control; some log raw event/error objects.
- **188 `any` usages** in web reduce type safety (esp. error handling).
- **Redis & DB defaults** in blockchain fall back to `localhost` / empty password — won't fail fast in prod.
- **`API_BASE_URL` duplicated** ~58× in web with `http://localhost:3000` fallback baked into production component files.
- **Docker** uses unpinned `node:latest` (non-reproducible builds); no `.nvmrc`/`engines` despite CI pinning Node 22.
- **CI gap:** the "Run Tests" job only builds — it never runs `npm test`. Deploys to prod/dev on push with `npm install` (not `npm ci`).
- **Migration `1768461271858-auto.ts`** is an auto-generated schema sync — review for unintended changes.
- **`.gitignore`** lists `!.env.example` but never ignores `.env` itself (real `.env` files are not gitignored — currently none committed, but the guard is missing).
- **README is stale** — describes a generic "PoC monorepo", mentions MongoDB while code uses Postgres.

---

## 6. What's Done Well

- Clean, consistent NestJS module structure; DI used throughout.
- Strong input validation: global `ValidationPipe` with `whitelist`+`forbidNonWhitelisted`; 385 class-validator decorators across 173 DTOs.
- No SQL injection surface — TypeORM parameterized queries; raw SQL only in migrations.
- Sound crypto hygiene: bcrypt (rounds 10), `crypto.randomBytes(32)` reset tokens, AES encryption of custody API keys via `CUSTODY_ENCRYPTION_KEY`.
- Global JSON exception filter; consistent Nest exceptions (547 throws).
- Production secrets sourced from **AWS SSM Parameter Store** at deploy time.
- Double-entry accounting uses DB transactions and immutable ledger entries.
- Web app: TanStack Query caching, strict TS, sensible provider layering, thirdweb (no self-custody keys).

---

## 7. Prioritized Remediation Roadmap

**Immediate (hours):**
1. Rotate the Alchemy key (C1); move it + Redis/DB config to env.
2. Strip secrets from `docker-compose.yml` / `init.sql` (C2).
3. Pin CORS origins on HTTP + WebSocket (C3); remove default Swagger password (H2).
4. Fix the broken blockchain e2e test; make CI actually run tests.

**Short term (1–2 weeks):**
5. Complete reward DB inserts and integrate a price oracle (C5) — financial correctness.
6. Add `helmet` + `@nestjs/throttler` (H3); hash reset tokens (H5); UUID-prefix S3 uploads (H4).
7. Move JWTs to httpOnly cookies + add CSRF (C6, H8); replace `dangerouslySetInnerHTML` with DOMPurify (H1).
8. Re-enable lint and TS strictness in admin/web/blockchain.

**Medium term (1–2 months):**
9. Build out test suites — target ≥50–70% on auth, custody, accounting, rewards (C4). Est. 100–150 hrs backend alone.
10. Add reorg handling + idempotency + retries to the indexer (H7).
11. Refactor oversized files (H9); centralize `API_BASE_URL`/avatar-URL utilities; add KYC workflow + audit trail (H6).
12. Prune the 208 remote branches.

---

## 8. Per-App Risk Summary

| App | Architecture | Security | Tests | Production-ready? |
|-----|:---:|:---:|:---:|:---:|
| backend | Good | High risk (CORS, uploads, reset tokens) | Critically low | ~70% |
| web | Good | High risk (localStorage JWT, XSS) | None | No |
| admin-panel | Good | High risk (client-side roles, no CSRF) | Minimal | No |
| blockchain | PoC | Critical (hardcoded key, no reorg/idempotency) | Broken | PoC only |

**Bottom line:** solid foundation and architecture, but treat as a late-stage prototype. Address the six critical items before exposing this to real users or funds.
