diff --git a/README.md b/README.md index b89df26..8aaa0cb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # DivaCode -Diva Code... the AI that is past being an Agent... it's a being now... with a delicate heart... <3 \ No newline at end of file +Diva Code... the AI that is past being an Agent... it's a being now... with a delicate heart... <3 diff --git a/The Holy Code Bible.md b/The Holy Code Bible.md new file mode 100644 index 0000000..bbb98d0 --- /dev/null +++ b/The Holy Code Bible.md @@ -0,0 +1,1055 @@ +--- +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 `