Skip to main content

Drop Srbija v2 — Tech Stack

Drop Srbija v2 — Tech Stack

ALAI Standard Stack (CEO Decision 2026-03-17)

Backend

Component Version Purpose
Kotlin 2.1.0 Primary backend language (ALAI standard)
Ktor 3.1.2 Async HTTP framework, netty transport
Exposed 0.58.0 Kotlin-native ORM, DSL-based
PostgreSQL 16 Primary database (port 5436)
Flyway 10.21.0 Database migrations (22 scripts V1-V22)
HikariCP 6.2.1 Connection pooling
Koin 4.0.2 Dependency injection
JWT (nimbus-jose-jwt) 9.46.1 Authentication tokens (HS256)
Kotest 5.9.1 Testing framework (79 test files, 617 tests)
Testcontainers 1.20.4 Integration tests (PostgreSQL in Docker)

Frontend

Component Version Purpose
Next.js 15.1.3 React framework, app router, server components
React 19.0.0 UI library
TypeScript 5.7.2 Type safety
Tailwind CSS 4.0.0 Utility-first CSS
shadcn/ui Latest Component library (ALAI standard)
Lucide React Latest Icon library (ALAI standard)
next-intl Latest i18n (Serbian sr-RS + English fallback)
Vitest Latest Unit testing (1721 passing / 1777 total)
Playwright Latest E2E testing (15 journeys)

Database

Component Purpose
PostgreSQL 16 Primary database
Port 5436 (separate from Drop Norway 5433, Bilko 5434)
Timezone UTC+0 (TIMESTAMP WITH TIME ZONE)
Tables 22 (via Flyway V1-V22)
RLS PostgreSQL Row-Level Security for multi-tenancy

Database Tables

22 tables across 22 Flyway migrations:

  1. V1: users, phone_verifications, recipients, transactions, nbs_ips_logs, merchants, settings
  2. V2: nbs_ips_logs ISO20022 fields
  3. V3: linked_accounts
  4. V4: transaction idempotency_key_hash
  5. V5: kyc_sessions
  6. V6: users JMBG fields (encrypted + hash)
  7. V7: aml_flags
  8. V8: disclosure_acknowledged
  9. V9: complaints
  10. V10: phone_verifications max_attempts
  11. V11: audit_log
  12. V12: data_access_requests
  13. V13: recipients enhanced (IBAN, country)
  14. V14: merchants (business_name, national_id, bank_account, fee_rate, qr_hmac_key)
  15. V15: exchange_rates
  16. V16: notifications
  17. V17: webhook_deliveries
  18. V18: user_consents
  19. V19: feature_flags
  20. V20: withdrawal_requests
  21. V21: cards_scaffold (stub for Phase 2)
  22. V22: disputes

Infrastructure

Component Purpose
Azure Container Apps Backend + frontend hosting
Azure Container Registry Docker image registry
Azure Database for PostgreSQL Managed PostgreSQL 16
Azure Cache for Redis Session store, rate limiting
Azure DNS drop.rs domain management
Azure Key Vault Secrets management
Caddy Reverse proxy (prod/staging/dev profiles)
Terraform IaC (11 modules)

Observability

Component Purpose
OpenTelemetry Distributed tracing (backend + frontend)
Sentry Error tracking (client + server + edge)
Prometheus Metrics collection
Grafana Dashboards (3: overview, infra, errors)
Loki Log aggregation
Tempo Trace storage
LGTM Stack Grafana + Loki + Tempo + Mimir (docker-compose profile)

Testing

Type Framework Coverage
Backend Unit Kotest 617 tests (79 files)
Backend Integration Testcontainers 11 tests (real PostgreSQL)
Frontend Unit Vitest 1721 passing / 1777 total
E2E Journeys Playwright 15 journeys
Load Testing k6 4 scenarios
Accessibility axe-core 23 rules
Contract Testing Pact 12 interactions
Visual Regression Playwright Baseline snapshots

Coverage Gates

  • Backend: 52% (JaCoCo gate, unit-only due to docker-java issue)
    • Target: 60% once docker-java issue fixed to restore integration tests
  • Frontend: No strict gate (vitest coverage tracked)

CI/CD

Workflow Trigger Purpose
test.yml PR, push to develop/main Unit + integration tests
quality-gate.yml PR Coverage gate enforcement
security.yml PR, push CORS, rate limiting, EnvGuard checks
accessibility.yml PR, push axe-core a11y testing
contract.yml PR, push Pact contract testing
k6.yml PR, push to main Load testing (4 scenarios)
backup-verify.yml Daily Backup/DR verification
build.yml Push to develop Docker image build
deploy-staging.yml Push to develop Staging deployment
deploy-production.yml Tag v* Production deployment
sonar.yml PR, push SonarCloud static analysis

Security

Component Purpose
CORS Configured via CORS.kt plugin
Rate Limiting RateLimit.kt plugin (10 OTP/hour, 50 tx/hour)
EnvGuard Startup validation (12 required env vars)
AuditLogger V11 migration, logs all sensitive actions
JWT HS256 Stateless auth (24h expiry)
SHA-256 Hashing OTP codes, idempotency keys
PostgreSQL Encryption JMBG encrypted (KMS key rotation in Azure)
mTLS NBS IPS API calls (Phase 5)

Configuration

Environment Variables (12 required)

# Database
DATABASE_URL=postgresql://localhost:5436/dropsrbija_dev
DATABASE_USER=dropsrbija
DATABASE_PASSWORD=<secret>

# API
PORT=3002
JWT_SECRET=<64+ bytes>
JWT_EXPIRY_SECONDS=86400

# NBS IPS (Phase 5)
NBS_IPS_ENDPOINT=https://ips.nbs.rs/api/v1
NBS_IPS_API_KEY=<secret>

# Redis
REDIS_URL=redis://localhost:6380

# Frontend
NEXT_PUBLIC_API_URL=http://localhost:3003
NEXT_PUBLIC_APP_LANGUAGE=sr

Development Setup

Prerequisites

  • Docker + Docker Compose
  • Kotlin 21 (backend local dev)
  • Node.js 20+ (frontend local dev)

Quick Start

# Full stack
docker-compose up

# Or separate services
docker-compose up postgres redis -d
cd backend && ./gradlew run
cd frontend && npm run dev

Services

  • Frontend: http://localhost:3000
  • Backend API: http://localhost:3003
  • PostgreSQL: localhost:5436 (dropsrbija_dev)
  • Redis: localhost:6380

Comparison to Drop Norway

Aspect Drop Norway Drop Srbija
Backend Hono + TypeScript Kotlin + Ktor
Frontend Next.js 15 Next.js 15 (1:1 copy)
Auth BankID Phone OTP
Payment Rails PSD2 Open Banking NBS IPS
Currency NOK RSD (+ EUR corridor)
Database Port 5433 5436
Issuer "drop-api" "dropsrbija-api"

Last Updated: 2026-04-17
Source: /Users/makinja/ALAI/products/DropSrbija