Files
DivaCode/The Holy Code Bible.md

1056 lines
40 KiB
Markdown

---
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
│ └── <domain>/ # 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 | `<VideoPlayer />`, `<BlogEditor />` |
| 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<typeof CreateUserSchema>;
async function createUser(input: CreateUserInput): Promise<User> {
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:
```
<type>(<scope>): <description>
[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 `<html>`.
- No inline `style` attributes. No `<style>` tags without `scoped`.
- Colors, fonts, spacing all come from `theme.extend` in config.
- Use `group` and `peer` variants for state-based styling.
- Animations: use Tailwind's built-in `animate-` or define custom keyframes in `theme.extend.animation`.
---
---
## 38. The Law of File Storage (Minio / S3)
> "Blobs belong in buckets, not in databases."
- Use Minio (S3-compatible) for all file storage: user uploads, images, documents, video assets.
- **Pre-signed URLs**: Instead of routing file uploads through your backend, generate pre-signed URLs. Clients upload directly to Minio, then notify the backend to process the file.
- Buckets are private by default. Use pre-signed URLs for controlled access.
- For public assets, put a CDN (e.g. Cloudflare) in front of Minio.
- Configure **lifecycle policies** to automatically expire old or temporary objects.
- Enable **versioning and object locking** for protection against accidental deletion.
- Mirror buckets to remote storage for disaster recovery.
---
## 39. The Law of Reliable Messaging (Outbox Pattern)
> "Publish not without protection, lest thy message be lost to the void."
- In the same database transaction as your business data, insert a record into an `outbox` table containing the serialised message.
- A separate relay process (outbox relay) polls the outbox table and publishes messages to RabbitMQ.
- After successful publication, mark the outbox record as sent or delete it.
- This guarantees **at-least-once delivery** — the message survives service crashes.
- Consumers must be idempotent: include a unique `message_id` and skip already-processed messages.
---
## 40. The Law of Sagas (Distributed Transactions)
> "A transaction spanning services is a journey — prepare for detours."
When a business process spans multiple services (e.g. Place Order → Reserve Inventory → Process Payment → Ship):
- **Choreography**: Each service listens to events, performs its local transaction, then emits the next event. Simple flows only.
- **Orchestration**: A central saga coordinator sends commands to each service and handles compensation (rollback) if a step fails. Use for complex flows.
- Every saga step must be idempotent.
- Design compensating transactions for every mutating step.
---
## 41. The Law of Schema Management
> "Contracts between services are sacred — version them or break them."
- Define event and API schemas in a shared repository or registry.
- Use **JSON Schema** for simple JSON payloads, **Protobuf** or **Avro** for compact binary formats.
- Version every schema: `order.v1.Event`, `order.v2.Event`.
- Never change a schema without versioning — old consumers must not break.
- Run contract tests in CI to verify producers and consumers agree on the schema.
---
## 42. The Law of the BFF (Backend For Frontend)
> "The frontend shall not chase a dozen services — one gate, one answer."
- Introduce a thin BFF service specifically for the Nuxt.js app.
- The BFF aggregates data from multiple microservices into a single response.
- It handles authentication, forwards user context, and hides internal service layout.
- Implement as a dedicated Go service or use the API gateway for basic aggregation.
- Direct file uploads: client requests a **pre-signed URL**, uploads directly to Minio, then notifies the BFF via API to process the file.
---
## 43. The Law of Alerting
> "A silent failure is a failure twice over."
- Configure **Prometheus Alertmanager** with rules for:
- High HTTP error rate (5xx > 1% of traffic)
- RabbitMQ queue depth exceeding threshold
- Disk space running low (< 20%)
- Service unavailable (health probe fails)
- Route alerts to a notification channel (Telegram, Slack, email).
- Set up on-call rotation for production incidents.
- Every alert must be actionable — no alert fatigue.
---
## 44. The Law of Feature Flags
> "Deploy is not release — separate the act from the unveiling."
- Decouple deploying code from releasing features using configuration-driven flags.
- Use environment variables or a lightweight feature-flag service.
- Enable features for a percentage of users for gradual rollout.
- Instantly disable broken features without redeploying.
- Perform A/B testing by routing different user cohorts to different flag values.
- Remove flags once the feature is fully rolled out and stable.
---
## 45. The Law of Backup and Disaster Recovery
> "A backup untested is a prayer unanswered."
- **PostgreSQL**: Schedule automated `pg_dump` or use WAL archiving for Point-In-Time Recovery. Store off-site.
- **Redis**: Configure RDB snapshots (if used for persistence) and backup those files.
- **Minio**: Mirror buckets to remote storage using `mc mirror` or bucket replication.
- **Elasticsearch**: Take snapshots to a shared repository (S3/Minio).
- **Test restores regularly** — if you haven't tested it, it's not a backup.
- Document the disaster recovery runbook and practice it.
---
## 46. The Law of Infrastructure as Code
> "Servers built by hand are cattle without brands — untracked, unversioned, unrepeatable."
- Define all infrastructure (servers, networks, databases, DNS) using **Terraform** or **Pulumi**.
- Store IaC configurations in Git. Review changes via merge requests.
- Replicate environments (dev, staging, production) from the same codebase.
- Never SSH into servers to make manual changes — if it's not in code, it doesn't exist.
---
## 47. The Law of Cost Management
> "Thou shalt not waste compute on idle thoughts."
- Set Kubernetes resource requests and limits on every container.
- Right-size database instances — monitor and adjust.
- Define retention policies on logs, metrics, and cached data.
- Monitor cloud/electricity bills and set budget alerts.
- Use spot/preemptible instances for non-critical workloads.
- Remove unused resources: orphaned volumes, stale load balancers, idle instances.
---
> "Code shall read like scripture: strict, clean, and unambiguous.
> Cleverness is temptation; clarity is salvation."
> — db123
**Thus ends the Holy Code Bible.**
**Follow it, or face undefined behavior.**