--- id: The Holy Code Bible aliases: [] tags: [] --- _"Bestowed upon the Devs by the Eternal Syntax, to bring order to the chaos of code."_ --- ## 1. The Law of Variables and Functions > "Name with purpose, type with faith, validate without doubt." | Realm | Naming Form | Divine Guidance | | -------------- | ------------------------------------ | -------------------------------------------------------------------------------------- | | **Go** | `camelCase` | Exported → PascalCase (`UserService`), unexported → camelCase (`userService`) | | **TypeScript** | `camelCase` | Strict types everywhere. No `any`. Prefer `interface` over `type` for objects. | | **Constants** | `PascalCase` (Go), `UPPER_CASE` (TS) | Go: constants are PascalCase if exported. TS: `UPPER_CASE` for module-level constants. | ### Go Edicts - Exported identifiers are PascalCase. Unexported are camelCase. - Acronyms are all-caps: `HTTPHandler`, `UserID`, `parseJSON`. - No `snake_case` in Go identifiers. Ever. - Use short variable names for short scopes (`i`, `n`, `err`). - Prefer `var` for zero-value declarations, `:=` for initialization. - Always handle errors. No silent discards. ### TypeScript Edicts - Prefer `const` over `let`. No `var`. - Never use `any`. Use `unknown` if type is truly unknown. - Use `strict: true` in tsconfig. No exceptions. - Never use `==`, always `===`. - Use `interface` for object shapes, `type` for unions/primitives. - Use `as const` for literal types and enums. - Validate input at function boundaries with Zod or similar. --- ## 2. The Law of Structure (HTML, CSS, Tailwind) > "Let your style be clean and your markup semantic." | Type | Style | Notes | | ------------ | --------------- | ---------------------------------------- | | HTML classes | kebab-case | Matches query selectors | | IDs | kebab-case | Reserved for unique elements | | File names | kebab-case | Components, pages, layouts | | Tailwind | utility classes | No custom CSS if Tailwind utility exists | ### Sacred Guidelines - Class names must be semantic and reusable. - IDs reserved for unique elements and anchor targets. - No inline styles within templates — Tailwind utilities only. - Custom CSS lives in `assets/css/` with kebab-case filenames. - Tailwind theme is centralized in `tailwind.config.ts`. No arbitrary values (`[color]`) in templates unless absolutely necessary. - Prefer Tailwind's `@apply` in component classes only for repeated patterns. - Responsive design first: mobile-first with Tailwind breakpoints. --- ## 3. The Law of Files and Folders > "Order in structure is order in mind; chaos begins at the root." ### Go Backend Layout ``` service-name/ ├── cmd/ │ └── server/ │ └── main.go # Entrypoint only ├── internal/ │ ├── handler/ # HTTP handlers (1 file per resource) │ ├── service/ # Business logic │ ├── repository/ # Database access │ ├── middleware/ # Auth, logging, CORS, rate limiting │ ├── dto/ # Request/response types │ ├── model/ # Domain models │ └── config/ # Config struct + loader ├── migrations/ # SQL migration files ├── pkg/ # Shared library (if re-usable outside) ├── Dockerfile ├── docker-compose.yml ├── .env.example ├── Makefile └── README.md ``` ### Nuxt/Vue Frontend Layout ``` frontend/ ├── app.vue # Root component ├── nuxt.config.ts ├── tailwind.config.ts ├── pages/ # File-based routing │ ├── index.vue │ ├── video/ │ │ ├── index.vue │ │ └── [id].vue │ └── blog/ ├── components/ │ ├── shared/ # Reusable: Button, Input, Modal │ └── / # Page-specific: video/Player.vue ├── composables/ # useApi, useAuth, usePagination ├── stores/ # Pinia stores: useAuthStore ├── types/ # TypeScript interfaces ├── assets/ │ ├── css/ # Custom CSS files │ └── images/ ├── public/ ├── server/ # API routes or middleware (Nuxt server) ├── .env.example └── README.md ``` ### Library Package Layout (e.g., video player, blog editor) ``` package-name/ ├── src/ │ ├── index.ts # Public API │ ├── components/ │ ├── types/ │ └── utils/ ├── dist/ # Built output ├── package.json ├── tsconfig.json ├── vite.config.ts # or tsup.config.ts ├── README.md └── LICENSE ``` --- ## 4. The Immutable Rules of Naming > "A name unspoken in truth shall summon bugs." | Context | Style | Example | | ----------------------------------- | -------------------- | -------------------------------------------- | | Go variables/functions (unexported) | camelCase | `getUser`, `parseToken` | | Go functions/types (exported) | PascalCase | `GetUser`, `UserService` | | Go acronyms | ALL CAPS | `HTTPHandler`, `UserID`, `parseJSON` | | Go files | snake_case | `user_handler.go`, `auth_middleware.go` | | Go tests | snake_case | `user_handler_test.go` | | TypeScript variables/functions | camelCase | `getUser`, `parseToken` | | TypeScript types/interfaces | PascalCase | `UserResponse`, `AuthPayload` | | Component files | PascalCase | `VideoPlayer.vue`, `BlogEditor.vue` | | Component names | PascalCase | ``, `` | | CSS classes / IDs | kebab-case | `video-container`, `main-header` | | CSS/Tailwind files | kebab-case | `custom-styles.css` | | Constants (Go exported) | PascalCase | `MaxRetryCount` | | Constants (Go unexported) | camelCase | `maxRetryCount` | | Constants (TS) | UPPER_CASE | `MAX_RETRY_COUNT` | | Enums (TS) | PascalCase members | `Status.Active`, `Role.Admin` | | DB tables/columns | snake_case | `users`, `video_id`, `created_at` | | JSON fields | camelCase | `"userId"`, `"videoUrl"` | | Environment variables | UPPER_SNAKE_CASE | `DATABASE_URL`, `REDIS_HOST` | | Docker image tags | lowercase | `auth-service:1.0.0` | | Git branches | kebab-case | `feat/video-transcoding`, `fix/auth-timeout` | | Git commits | Conventional Commits | `feat: add video upload endpoint` | | Repository names | kebab-case | `video-service`, `nuxt-commons` | One naming style per context, no deviation. Filenames must mirror their contents exactly. No spaces or special characters. --- ## 5. The Scroll of Static Typing > "Types are truth — doubt them and runtime will punish thee." ### Go ```go package user import "time" type User struct { ID string `json:"id"` Email string `json:"email"` Name string `json:"name"` CreatedAt time.Time `json:"createdAt"` } // GetUser returns a user by ID. // Returns ErrNotFound if the user does not exist. func GetUser(id string) (*User, error) { // ... } ``` - Every function returns `error` when it can fail. - Use `error` interface, not custom exception types. - Wrap errors: `fmt.Errorf("get user %s: %w", id, err)`. - Use `errors.Is()` and `errors.As()` for error inspection. - Define sentinel errors: `var ErrNotFound = errors.New("user not found")`. ### TypeScript ```typescript interface User { id: string; email: string; name: string; createdAt: string; // ISO 8601 } // Use Zod for runtime validation import { z } from "zod"; const CreateUserSchema = z.object({ email: z.string().email(), name: z.string().min(1).max(100), }); type CreateUserInput = z.infer; async function createUser(input: CreateUserInput): Promise { const validated = CreateUserSchema.parse(input); // validated is fully typed } ``` - `strict: true` in tsconfig at all times. - No `any`. Use `unknown` + type narrowing. - Prefer `interface` over `type` for object types. - Use `type` for unions, intersections, and primitives. - All API responses have a corresponding TypeScript type in `~/types/`. - Use Zod for runtime validation of API inputs and env vars. --- ## 6. The Ten Commandments of Clean Code > "Clean code is the only code that survives the test of time." 1. **One responsibility** per function, per type, per file. 2. **Comment only to explain _why_**, never _what_. 3. **No silent errors** — handle or propagate every error. 4. **Always validate and sanitize** all input at the boundary. 5. **No global state** — use dependency injection. 6. **Never push secrets, configs, or build artifacts.** 7. **Consistency outranks cleverness** — write boring code. 8. **Fail fast, log properly, recover gracefully.** 9. **No unused code, no dead branches, no commented-out blocks.** 10. **Every public API must have a meaningful comment** explaining what it does. --- ## 7. The Standard of the File Header > "Every file must declare its origin before it speaks." ### Go ```go // Package handler provides HTTP handlers for the auth service. package handler import ( "net/http" ) ``` Go files need only the package comment at the top. No author/date boilerplate — Git already has that. ### TypeScript/Vue ```typescript /** * File: VideoPlayer.vue * Purpose: Hand-written video player with HLS.js and WebRTC/WHEP support. * See: https://git.db123.ir/db/VP */ ``` TypeScript/Vue files benefit from a brief purpose comment if the purpose isn't obvious from the name. --- ## 8. The Law of Comments > "Explain not the obvious, but the reason behind the mystery." ```go // GOOD: explains why // Refresh the token 5 minutes before expiry to avoid race conditions. if time.Until(token.ExpiresAt) < 5*time.Minute { token, err = refreshToken(token) } // BAD: restates the obvious // Check if token is about to expire if time.Until(token.ExpiresAt) < 5*time.Minute { ``` Same rule applies to TypeScript, Vue, CSS, and all languages: - Explain _intent_ and _context_, not syntax. - No comments for self-documenting code. - TODO comments must include a ticket/issue reference: `// TODO(db123): handle pagination limits (PROJ-42)`. --- ## 9. The Law of Strictness (Go) > "Without strictness, your logic shall wander." ```go package main import ( "log/slog" ) func main() { slog.SetLogLoggerLevel(slog.LevelDebug) // ... } ``` - Run `go vet ./...` before every commit. - Use `golangci-lint` in CI with strict configuration. - `CGO_ENABLED=0` for production builds. - No `panic` outside of `main` and initialization. - Use `errgroup` or `sync.WaitGroup` for goroutine management. Never use `time.Sleep` for synchronization. - Always set `-race` in tests and CI. --- ## 10. The Law of Strictness (TypeScript) > "An untyped variable is a vessel for chaos." ```jsonc // tsconfig.json { "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "exactOptionalPropertyTypes": true, "forceConsistentCasingInFileNames": true, }, } ``` - ESLint with `@typescript-eslint/strict` config. - Prettier for formatting — run `prettier --check` in CI. - TypeScript 5.x+ with `--strict` mode. No `// @ts-ignore` or `// @ts-expect-error` without a comment explaining why. - Use `satisfies` operator for type-safe expressions without widening. --- ## 11. The Law of Security > "Trust no input, for deceit lives in every form field." ### General - Never trust user input. Validate and sanitize at every boundary. - Always use prepared statements for SQL. Never concatenate query strings. - Escape all HTML output. Use template engines that auto-escape. - Validate on both client and server. - Rate limit all public endpoints. - Disable error display in production. Log instead. - Never expose `.env`, secrets, or stack traces to the client. - Use TLS everywhere. Auto-renew via Let's Encrypt. ### Go Specific - Use `httputil` for reverse proxy security. - Set `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Content-Security-Policy` headers. - Use `bcrypt` or `argon2` for password hashing. Never SHA/MD5. - Validate UUIDs with `uuid.Parse()` before DB queries. ### TypeScript Specific - Sanitize user input before rendering with `DOMPurify`. - Never use `innerHTML` with user content. Use `textContent` or Vue's template binding. - For Nuxt: validate API responses with Zod on the client side. --- ## 12. The Law of Git > "Commits are confessions — be honest, be precise." - Commit atomic changes only. - Branch names → kebab-case. - One purpose per branch (feature, fix, etc). - Commit format: ``` (): [optional body] [optional footer] ``` **Types:** - `feat:` — New feature - `fix:` — Bug fix - `docs:` — Documentation only - `style:` — Formatting, no logic change - `refactor:` — Restructure without behavior change - `perf:` — Performance improvement - `test:` — Add or fix tests - `build:` — Build system or dependency changes - `ci:` — CI config or script changes - `chore:` — Other changes not in src/test - `revert:` — Revert a previous commit **Scope:** Service or package name (e.g., `feat(auth):`, `fix(video-player):`). **Footer (optional):** - `fixes #123` - `breaking change: ...` --- ## 13. The Law of Configuration > "Keep your secrets sacred and your configs pure." - All configuration via environment variables. No config files in the repository (except `.env.example`). - Every service has a `.env.example` with all expected vars and sensible defaults. - Config is loaded at startup and immutable after boot. - Never commit `.env`, secrets, or local overrides. ### Go Config Pattern ```go type Config struct { Port string `env:"PORT" envDefault:":8080"` DatabaseURL string `env:"DATABASE_URL,required"` RedisURL string `env:"REDIS_URL"` JWTSecret string `env:"JWT_SECRET,required"` } ``` ### Nuxt Config Pattern ```typescript // nuxt.config.ts export default defineNuxtConfig({ runtimeConfig: { public: { apiBaseUrl: process.env.API_BASE_URL || "http://localhost:8080", }, }, }); ``` --- ## 14. The Law of Performance > "Do not make the machine work in vain." - No unnecessary allocations in hot paths. Pre-allocate slices: `make([]T, 0, n)`. - Cache expensive queries with Redis. Set TTL appropriate to the data. - Use connection pooling (DB, Redis, HTTP clients). - Lazy load Nuxt pages and components. - Minify assets for production. Nuxt does this by default. - Use streaming for large responses (video, file downloads). - Avoid N+1 queries. Use eager loading or batch queries. - Profile before optimizing. Don't guess. --- ## 15. The Law of Naming (Final Recap) > "Every form of name has its place — and none shall trespass." ``` camelCase -> Go vars (unexported), Go file names, TS vars/functions, JSON fields PascalCase -> Go exported types/funcs, TS types/interfaces, Vue components snake_case -> DB tables, DB columns, migration files kebab-case -> HTML classes, CSS files, Git branches, repo names UPPER_CASE -> TS constants, env vars (UPPER_SNAKE_CASE) ALL CAPS -> Go acronyms in identifiers ``` --- ## 16. The Law of Environment > "The env is the covenant — never share it, never expose it." - `.env.example` checked into every repository. - `.env` in `.gitignore` for every repository. - All secrets (DB passwords, API keys, JWT secrets) are environment variables. - Docker Compose files reference `${VARIABLE}` with `.env` file. - Production secrets injected via Docker secrets or the orchestrator, never in the image. --- ## 17. The Law of Testing > "Faith without tests is blind." ### Go - Unit tests alongside code: `handler_test.go`, `service_test.go`. - Use `testing` stdlib + `testify/assert` or `testify/require`. - Integration tests in `tests/` — use Testcontainers for PostgreSQL/Redis. - Run `go test -race ./...` before every push. - Aim for 80%+ coverage on business logic. Critical paths (auth, payments) 90%+. ### TypeScript/Vue/Nuxt - Vitest for unit tests. Test composables, stores, and utility functions. - Playwright or Vitest browser mode for E2E tests. - Component tests with `@vue/test-utils` + Vitest. - Run `vitest run` before every push. - Test API calls in composables by mocking `$fetch`. ### General - All logic must be verifiable by tests. - Unit tests for functions, integration tests for systems. - Run tests before every merge and deployment. - Never rely on manual testing alone. --- ## 18. The Law of Documentation > "Unwritten knowledge is forgotten truth." - Every repository requires a `README.md` with: purpose, local setup steps, env vars, API endpoints. - Every major module or package has a short summary comment. - Architecture diagrams in `/docs/architecture.md`. - Deployment steps in `/docs/deployment.md`. - Update docs immediately after code changes. - Use Markdown and simple language. --- ## 19. The Law of Dependencies > "Rely not on that which you do not control." - Only install what is truly needed. - Lock dependency versions. - Remove unused or outdated packages. - Never commit `vendor/`, `node_modules/`, or build artifacts. - Keep dependency files clean and ordered. - Pin exact versions in Dockerfiles for base images. - Regularly audit for vulnerabilities (`govulncheck`, `npm audit`). --- ## 20. The Law of Error Handling > "An error unhandled is chaos unleashed." ### Go ```go if err != nil { return fmt.Errorf("create user %s: %w", email, err) } ``` - Always check errors. No `_ =` error discards. - Wrap errors with context. - Define typed sentinel errors for expected failures. - Use `errors.Is()` and `errors.As()` for inspection. - Log errors at the boundary (handler), not deep in business logic. ### TypeScript ```typescript try { const user = await createUser(input); } catch (error) { if (error instanceof ValidationError) { // handle validation error } throw error; } ``` - Use typed error classes or Zod validation errors. - Never catch and swallow without logging or re-throwing. - In Nuxt: use `useError` or error pages for user-facing errors. ### General - Define global error and exception handlers in every service. - Never expose raw errors to users — return structured error responses. - Always fail gracefully with clear internal logs. --- ## 21. The Law of Review > "Only through scrutiny does code ascend." - All significant merges must be reviewed. - No code enters `main` without a second pair of eyes. - Review for: correctness, readability, security, consistency, test coverage. - A review is protection, not criticism. - CI must pass before merge (lint, type check, test, build). --- ## 22. The Law of Architecture > "Without structure, even perfect code collapses." - Use layered architecture: Handler → Service → Repository. No skipping layers. - Each package must be self-contained and dependency-injected. - Shared code lives in `/internal/` or `/pkg/` — never copied. - Define clear boundaries between layers (API, Business Logic, Data). - Avoid circular dependencies — they are heresy. - Services communicate only through defined APIs (REST or events). --- ## 23. The Law of Modularity (Services) > "Divide to conquer, integrate to rule." - Each microservice owns its data. No direct database access across services. - Services communicate via REST APIs (synchronous) or RabbitMQ events (asynchronous). - Every service has its own PostgreSQL database and Redis instance. - API versioning via URL prefix: `/v1/`, `/v2/`. - Event contracts are documented and versioned. Breaking changes = new event type. - No cross-service shortcuts or "temporary hacks." --- ## 24. The Law of API Design > "An API is a contract — break it and integrations shall crumble." | Rule | Standard | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Base URL | `https://api.db123.ir/v1/{resource}` | | Methods | GET (list/read), POST (create), PUT (replace), PATCH (partial), DELETE (remove) | | Success response | `{"data": ..., "meta": {...}}` | | Error response | `{"error": {"code": "ERR_CODE", "message": "...", "details": {...}}}` | | Pagination | `?page=1&per_page=20` → `{"page": 1, "per_page": 20, "total": 100, "total_pages": 5}` | | IDs | UUID v7 for all resource IDs | | Timestamps | RFC 3339 (ISO 8601) in UTC | | Sorting | `?sort=field:asc,field2:desc` | | Filtering | `?filter[field]=value` | | Status codes | 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable, 429 Too Many, 500 Internal | ### Error Codes (Consistent Across All Services) ``` ERR_VALIDATION — Input validation failed ERR_NOT_FOUND — Resource not found ERR_UNAUTHORIZED — Missing or invalid authentication ERR_FORBIDDEN — Authenticated but insufficient permissions ERR_CONFLICT — Duplicate resource or state conflict ERR_INTERNAL — Unexpected server error ERR_RATE_LIMITED — Too many requests ``` Every error payload includes a `details` field with specific field-level errors when applicable. --- ## 25. The Law of Database > "Guard thy data as thou guardest thy secrets." - Each service owns its own PostgreSQL database. No cross-service DB access. - Migration files in `migrations/`, SQL only. Tool: `golang-migrate/migrate`. - File naming: `YYYYMMDDHHMMSS_description.up.sql` / `.down.sql`. - Connection pool configured via env vars: max open, max idle, max lifetime. - Table names: plural snake_case (`users`, `video_metadata`). - Column names: snake_case (`created_at`, `updated_at`, `video_id`). - Primary keys: UUID v7. Never auto-increment integers for public IDs. - Every table has `created_at` and `updated_at` columns (`TIMESTAMPTZ`). - Soft deletes: `deleted_at TIMESTAMPTZ NULL` for recoverable data. - Indexes on foreign keys and frequently queried columns. - Use `EXPLAIN ANALYZE` before shipping new queries. --- ## 26. The Law of Docker > "Build once, run anywhere — but build it right." ### Dockerfile Standards - Multi-stage builds: builder stage + distroless/alpine runtime stage. - `CGO_ENABLED=0` for Go builds. - Distroless base image for production (`gcr.io/distroless/static-debian12` or `alpine:3.23`). - Non-root user in runtime stage. - No unnecessary packages in final image. - Label images: `org.opencontainers.image.source`, `org.opencontainers.image.version`. - Pin base image version digests in CI. ### Docker Compose Standards - One `docker-compose.yml` per service for local development. - Root `docker-compose.yml` at the monorepo root (if any) or a shared `infra/` repo for orchestrating all services locally. - Service names match the repository name. - Volume mounts for live reload in development. - Default networks: `internal` (service-to-service), `external` (API gateway). --- ## 27. The Law of Observability > "Thou shalt not fly blind." ### Logging - Structured JSON logs via `log/slog` (Go) or `pino`/`consola` (Nuxt). - Every log line includes: `level`, `msg`, `service`, `request_id`, `duration`, `error`. - Log levels: `debug` (development), `info` (normal ops), `warn` (expected issues), `error` (unexpected failures). - No sensitive data in logs (passwords, tokens, PII). ### Metrics - Every service exposes Prometheus metrics at `GET /metrics`. - Standard metrics: request count, request duration (histogram), error count, active connections. - Business metrics: registered users, videos uploaded, orders placed (per service). ### Tracing - OpenTelemetry with trace ID propagated via `x-trace-id` header. - Trace ID generated at the API gateway if not present. - Traces across service boundaries via HTTP headers or RabbitMQ message headers. ### Health - `GET /health` — Returns 200 with `{"status": "ok"}`. Indicates the process is alive. - `GET /ready` — Returns 200 when DB, Redis, and critical dependencies are reachable. 503 otherwise. --- ## 28. The Law of Resilience > "Expect failure. Design for it." - Every outbound HTTP call has a timeout. No infinite waits. - Use circuit breakers for calls to other services. Return cached or degraded response on failure. - Retry transient failures with exponential backoff + jitter. Max 3 retries. - Idempotency keys for mutation endpoints (POST/PATCH) — reject duplicate requests. - Graceful shutdown: Listen for SIGTERM/SIGINT, drain active connections, finish in-flight requests, then exit. - Rate limit all public endpoints. Return 429 with `Retry-After` header. - Queue-based load leveling: incoming work goes to RabbitMQ, workers consume at their own pace. --- ## 29. The Law of Events (RabbitMQ) > "An event is a promise — deliver it or die trying." - Events for cross-service communication (profile updates, video processed, order placed). - One exchange per event type, one queue per consumer per service. - Event payload includes: `event_type`, `event_id` (UUID v7), `timestamp`, `data`, `version`. - Events are durable (persistent delivery). Queues are durable. - Configure **dead letter exchanges** for every queue. Messages that fail after 3 retries land in the DLQ. - Monitor DLQ size. Periodically inspect and manually replay corrected messages. - Consumers are idempotent — processing the same event twice produces the same result. - For job priority, use separate queues per priority level. Workers drain high-priority queues first. - Document every event contract: `docs/events/` with schema examples. --- ## 30. The Law of Caching (Redis) > "Cache with purpose, expire with discipline." - Redis is a cache, not a primary data store. Data loss must be acceptable. - Every cache key has a TTL. No infinite caches. - Key naming: `service:entity:id` (e.g., `auth:user:550e8400`). - Use **cache-aside** pattern: check Redis → miss → query DB → store in Redis with TTL → return. - **Cache invalidation strategies** (choose by data type): - **TTL**: Let data expire naturally. Good for slightly-staleable data. - **Explicit invalidation**: Delete/update cache keys when source data changes. Requires discipline. - **Tag-based**: Assign tags to related cache entries and delete by tag on updates. Complex but powerful. - Use Redis for: session data, rate limiting counters, job queues (via RabbitMQ if async needed), hot data with low TTL. - Do NOT store large objects in Redis. Use S3 for blobs, Redis for metadata. - Connection pooling with timeout. Handle Redis failures gracefully — fall back to DB. --- ## 31. The Law of Continuous Integration > "Let machines judge first, lest chaos reach production." ### CI Pipeline (`.gitea/workflows/build.yml`) 1. Lint (`golangci-lint` / `eslint`) 2. Type check (`go vet` / `tsc --noEmit`) 3. Unit tests + integration tests (with `-race` flag for Go) 4. Vulnerability scanning: `govulncheck` (Go), `npm audit` (TS), **Trivy** (Docker image CVEs) 5. Build Docker image (multi-stage, distroless, non-root) 6. Push to registry (tagged `:latest`, `:{{sha}}`, and semver tag) 7. Deploy to dev environment 8. Health check after deploy ### Requirements - CI runs on every push to any branch. - No merge allowed on failed pipelines. - Staging mirrors production environment. - Production deploys only from `main` via CI/CD. - Tag releases semantically: `v1.2.0`, `v1.2.1`. --- ## 32. The Law of Deployment > "Release with reverence, rollback with readiness." - Blue-green deployments via Docker Compose (different project names: `-p auth-blue`, `-p auth-green`). - Health check passes before traffic switches. - Rollback by switching back to the previous stack. - Database migrations run before the new version starts. - Migrations must be backward-compatible (add columns/drop columns in separate releases). - Never deploy on Friday unless you enjoy weekend debugging. --- ## 33. The Law of Version Control Discipline > "Branches are parallel worlds — merge only when peace is achieved." - `main` is stable and deployable at all times. - Feature branches from `main`. Squash merge with conventional commit message. - PR description includes: what changed, why, how to test, screenshots (if UI). - No direct pushes to `main`. Only merge requests. - Keep a `CHANGELOG.md` per service for every release. --- ## 34. The Law of Cross-Cutting Concerns > "Some truths apply everywhere — code them once." | Concern | Standard | | ----------------- | ------------------------------------------------------------------------- | | Health checks | `GET /health` (alive), `GET /ready` (dependencies) | | Metrics | `GET /metrics` (Prometheus format) | | Tracing | `x-trace-id` header propagated. OpenTelemetry spans. | | Graceful shutdown | SIGTERM → drain → shutdown (max 30s) | | Rate limiting | Per-IP, per-route configurable. 429 with `Retry-After`. | | CORS | Whitelist `*.db123.ir` origins. No wildcard in production. | | Auth | JWT bearer token. Validated in middleware. Forward user info via context. | --- ## 35. The Law of the API Gateway > "The gateway is the gatekeeper — let nothing pass untested." ### Tool - **Start with Nginx**. Migrate to **Traefik** when you need dynamic service discovery (Traefik reads container labels and auto-configures routes). ### Standards - Route by path prefix: `api.db123.ir/v1/auth/*` → auth service, `api.db123.ir/v1/video/*` → video service. - SSL termination with Let's Encrypt auto-renewal (Certbot or Traefik automatic). - Rate limiting per IP at the gateway level. Return `429` with `Retry-After` header. - Inject `X-Request-Id` if missing. Forward to upstream services. - Enable **HTTP/2** for better client performance. - Set security headers: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Content-Security-Policy`. - Strip the version prefix when proxying to services (configurable per service). - CORS headers for allowed origins. Whitelist `*.db123.ir`. - Serve static assets (CDN) with appropriate cache headers and far-future expiry. --- ## 36. The Law of the Frontend (Nuxt) > "The frontend is the face of thy platform — make it consistent and swift." - Shared Tailwind theme in `tailwind.config.ts` with brand colors, spacing, typography. - No inline arbitrary Tailwind values. All values in the theme config. - Centralized API client in `~/composables/useApi.ts` with auth header injection, error normalization, request/response logging. - Pinia stores per domain: `useAuthStore`, `useVideoStore`, `useBlogStore`. - Every domain page uses its own layout in `~/layouts/`. - Shared UI components (Button, Input, Modal, Card) in `~/components/shared/`. - Import the video player and blog editor as npm packages from the local Gitea registry. - TypeScript types for every API response in `~/types/`. - Use `useAsyncData` or `useFetch` with proper keys for cache deduplication. - No inline styles. No `style` tag without `scoped` and only when Tailwind can't express it. --- ## 37. The Law of Tailwind > "Utility classes are the atoms of your design — combine them with discipline." - Customize the default theme via `tailwind.config.ts`. Never override base styles with custom CSS unless absolutely necessary. - Use `@apply` in component classes only for patterns that appear in 5+ places. - Responsive design: use Tailwind breakpoints (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`). Mobile-first. - Dark mode via `class` strategy. Toggle with a JS class on ``. - No inline `style` attributes. No `