Add three new NestJS modules following DDD/CQRS architecture:
- Industrial: KCN (industrial park) management with PostGIS geo queries, Typesense search, and market statistics
- Transfer: Furniture/premises transfer listings with AI-powered price estimation and depreciation modeling
- Reports: Async AI report generation via BullMQ with Claude narrative service, PDF generation, and macro data integration
Includes Prisma schema models, migrations, seed scripts, and app.module wiring with BullMQ Redis config.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Expand production monitoring with full alert coverage for database connections,
Redis memory/connections, container resources, disk usage, service health, and
backup integrity. Add Alertmanager service with Slack routing for critical and
warning alerts, and add automated backup verification to the pg-backup cron
schedule. Update runbook with DR validation procedures and quarterly checklist.
- Expand Prometheus alert rules from 4 to 24 alerts across 7 groups
- Add Alertmanager container (prom/alertmanager:v0.27.0) with Slack routing
- Configure inhibition rules (critical suppresses warning for same service)
- Schedule automated backup verification at 04:00 UTC daily
- Add Alertmanager datasource to Grafana provisioning
- Update runbook with Section 9: DR Validation (automated + manual procedures)
- Add SLACK_WEBHOOK_URL and Grafana vars to .env.example
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Introduces PgBouncer as a connection pooler between the API service and
PostgreSQL in docker-compose.prod.yml, reducing connection overhead and
improving concurrency under production load.
- Add PgBouncer service (edoburu/pgbouncer:1.23.1-p2) with transaction
pool mode, max_client_conn=200, default_pool_size=20
- Route API DATABASE_URL through PgBouncer (port 6432), keep direct
connection (DATABASE_URL_DIRECT) for Prisma migrations/introspection
- Create infra/pgbouncer/ config: pgbouncer.ini, userlist template,
and entrypoint script with runtime env-var substitution
- Update prisma.config.ts to prefer DATABASE_URL_DIRECT for migrations
- Add K6 load test (e2e/load/pgbouncer-pool-test.js) with ramp-up to
200 VUs, pool exhaustion detection, and p95 < 2s threshold
- Add PgBouncer env vars to .env.example
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The env-validation module previously only checked that JWT_SECRET and
JWT_REFRESH_SECRET were _present_ — it accepted any value, including
known placeholders like "CHANGE_ME". This meant a developer could copy
.env.example verbatim and run the app with predictable, forgeable tokens.
Changes:
- Add FORBIDDEN_SECRET_VALUES blocklist (case-insensitive) with 23 common
placeholder strings (CHANGE_ME, secret, password, test, etc.)
- Enforce minimum 32-character length for JWT secrets (NIST HMAC guidance)
- Export validateJwtSecret() for direct testing and reuse
- Update .env.example: replace "CHANGE_ME" with generation instructions
- Add 14 unit tests covering placeholder rejection, length enforcement,
missing-var errors, and production-mode validation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add complete OAuth2 authentication flow for Google and Zalo providers:
- OAuthService: handles account linking (by email/phone), new user
creation for OAuth-only accounts, and JWT token generation
- GoogleOAuthStrategy: passport-google-oauth20 integration
- ZaloOAuthStrategy: custom OAuth2 implementation using Zalo's API
(authorization URL generation, code exchange, user info fetch)
- OAuthController: redirect and callback endpoints for both providers
with httpOnly cookie-based token management
- Unit tests for OAuthService (7 tests), GoogleOAuthStrategy (4 tests),
and ZaloOAuthStrategy (7 tests)
- OAuth env vars added to .env.example and env-validation warnings
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add startup env validation that fails fast in production if critical vars
(JWT_SECRET, JWT_REFRESH_SECRET, DATABASE_URL, CORS_ORIGINS, REDIS_HOST)
are missing
- Fix CORS_ORIGINS to throw in production instead of defaulting to localhost
- Replace hardcoded dev passwords in .env.example with CHANGE_ME placeholders
- Add missing vars to .env.example (CORS_ORIGINS, SMTP_*, FIREBASE, LOG_LEVEL)
- Warn on missing optional payment/storage vars at startup
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The auth module fell back to a publicly-known secret string when JWT_SECRET
was unset, creating a critical authentication bypass risk. Both jwt.strategy.ts
and auth.module.ts now throw at startup if JWT_SECRET is missing.
Co-Authored-By: Paperclip <noreply@paperclip.ing>