# YalArba (ЯлАрба) — Tourist Aggregator **Generated:** 2026-06-12 **Commit:** 165d5a5 **Branch:** main ## OVERVIEW Go REST API backend (chi router + GORM + PostgreSQL) with docker-compose orchestration. SPA frontend via Nginx reverse proxy + Certbot. Goose for DB migrations. JWT auth via HttpOnly cookies. ## STRUCTURE ``` ./ ├── api/ # Go backend service │ ├── cmd/main.go # Entry point │ ├── src/ │ │ ├── configs/ # Server + DB config structs │ │ ├── initializers/ # Chi routing + GORM DB init │ │ ├── models/ # GORM models (User, Essence, Contact, Point) │ │ ├── rt/ # Route handlers grouped by domain │ │ │ ├── auth/ # Login, Register, JWT middleware │ │ │ ├── admin/ # Admin-only endpoints │ │ │ ├── prf/ # Profile (stub) │ │ │ └── srch/ # Search (stub) │ │ └── storages/psql/ # Global *gorm.DB var │ └── Dockerfile ├── migrator/ # Goose migration runner │ └── migrations/ # Timestamped SQL migrations ├── spa/ # Nginx + static HTML landing + certbot │ ├── index.html # Landing page (Russian) │ └── data/nginx/ # Nginx config ├── docker-compose.yaml # services: db, api, migrator, spa, certbot ├── Makefile # build, run, clean, test └── .env # Environment variables (DO NOT COMMIT) ``` ## WHERE TO LOOK | Task | Location | Notes | |------|----------|-------| | Add API route | `api/src/initializers/Routing.go` + `api/src/rt/` | Register handler in Routing.go; create handler in rt/ subdir | | Add DB model | `api/src/models/` | GORM struct with json + gorm tags; UUID PKs | | Add migration | `migrator/migrations/` | Goose format: timestamp_description.sql | | Auth logic | `api/src/rt/auth/` | JWT in HttpOnly cookie; claims in request context | | DB access | `api/src/storages/psql/psql.go` | Global `PSQL_GORM_DB *gorm.DB` | | Config/env vars | `.env` → `os.Getenv()` in code | Config structs in `api/src/configs/` | ## CODE MAP | Symbol | Type | Location | Role | |--------|------|----------|------| | `main` | func | `api/cmd/main.go:16` | Entry: calls InitChiRouting + InitDBconnection | | `InitChiRouting` | func | `api/src/initializers/Routing.go:21` | Sets up chi router, middlewares, all routes | | `InitDBconnection` | func | `api/src/initializers/PGQL_DB.go:14` | GORM Postgres connection, sets psql.PSQL_GORM_DB | | `PSQL_GORM_DB` | var | `api/src/storages/psql/psql.go:5` | Global DB handle | | `Login` | func | `api/src/rt/auth/Login.go:21` | Validates creds, issues JWT cookie | | `Register` | func | `api/src/rt/auth/Registr.go:54` | Validates input, hashes password, creates user | | `AuthMiddleware` | func | `api/src/rt/auth/authMiddleware.go:11` | JWT cookie validation middleware | | `AuthAdminMiddleware` | func | `api/src/rt/auth/authAdminMiddlware.go:11` | JWT + role=admin check | | `User` | struct | `api/src/models/user.go:5` | GORM model: id, name, email, password, phone, role | | `Claims` | struct | `api/src/models/authDataStructs.go:15` | JWT claims: email, phone, role | ## CONVENTIONS - **Naming**: Go package names are short abbreviations (auth, prf, srch, admin). File names in PascalCase. - **DB**: GORM with UUID PKs (`AutoIncrement:false`). Goose for migrations with timestamp prefixes. - **Auth**: JWT stored in HttpOnly/Secure/SameSite cookie. Role stored in claims. Context key is `"email"`. - **Config**: All config via `os.Getenv()`, no config files. `.env` loaded by docker-compose. - **Logging**: `log/slog` structured logging. - **Errors**: `http.Error()` for simple errors. JSON-encoded `validationError` struct for validation. - **Password**: bcrypt cost 14. Max password length 72 (bcrypt limit). - **Role defaults**: Empty role on registration → "user". ## ANTI-PATTERNS (THIS PROJECT) - `os.Exit(2)` on DB failure — kills entire process, no graceful shutdown - Duplicate JWT parsing logic between `authMiddleware.go` and `authAdminMiddlware.go` - `authAdminMiddlware.go` has typo in filename ("Middlware") - `AuthUserMiddleware.go` in prf/ is a dead stub (always 401) - Global mutable state (`PSQL_GORM_DB`, package-level `jwtKey`) - HTTPS enforced on JWT cookies but HTTP port 80 exposed — mismatch in dev - `AGENTS.md` in `.gitignore` because it previously contained secrets — credentials belong in `.env` only ## COMMANDS ```bash make # docker compose up (default) make build # docker compose build make run # docker compose up make clean # docker builder prune make test # go test ./api/src/auth/... -v make tc # go test -cover ``` ## NOTES - `.env` contains real secrets — never commit. The `.gitignore` entry for `AGENTS.md` was added because it previously held credentials. Remove that `.gitignore` line once this file is clean. - `Profile` and `Search` handlers are stubs (empty bodies). - Docker services depend on each other: db → api → migrator → spa+certbot. - Goose migration `GOOSE_DBSTRING` in `.env` must match PG credentials.