# Code Standards

<!-- markdownlint-disable MD013 -->

## Coding Style

- Target Python 3.11+ with full type hints; treat warnings as errors in CI when feasible.
- Use pyproject.toml to centralize tool config.
- Formatting: Black (line-length 88), with Ruff handling import sorting (isort rules).
- Linting: Ruff as primary linter (flake8 rules), enable complexity and performance checks.
- Static typing: mypy strict-ish (warn-unused-ignores, disallow-incomplete-defs). Prefer typing.Protocol over runtime ABCs for contracts.
- Structure: src/ layout; small, cohesive modules; avoid cyclic imports; prefer dataclasses or Pydantic models for data.
- Errors: no bare except; catch specific exceptions; re-raise with context; avoid returning None on error paths.
- Logging: standard logging with structured JSON in production; no print; log at the edge, not in hot paths; never log secrets.
- Naming: snake_case for functions/vars, PascalCase for classes, UPPER_CASE for constants; explicit __all__ in public modules.

## Documentation

- Docstrings: Google style (or NumPy) on all public functions/classes; include types and error cases.
- README: quickstart, architecture overview, local dev, testing, deployment.
- ADRs (short) for non-trivial decisions.
- Developer docs via MkDocs + mkdocstrings (optional).
- Inline comments for non-obvious logic; keep comments close to code.
- Provide minimal runnable examples for public APIs/CLIs.
- Keep CHANGELOG with Keep a Changelog format.

## Testing

- Framework: pytest with tests/ mirroring src/; name tests as test_*.py.
- Coverage: 90%+ branch coverage; fail CI below threshold; exclude trivial __main__ guards.
- Test types:
  - Unit: fast, isolated, pure; heavy use of fixtures/factories.
  - Integration: real DB/services via docker-compose; label with pytest markers (e.g., integration, slow).
  - Property-based tests (hypothesis) for core logic.
- Mocks: pytest-mock; avoid over-mocking; favor fakes for complex collaborators.
- Determinism: seed RNG; freeze time when relevant.
- Run tests in CI on multiple Python versions if feasible.
- Generate JUnit XML and coverage XML for CI publishing.

## Security

- Secrets: only via environment or secret manager; never commit; provide .env.example; validate required env vars at startup.
- Dependencies: pin and lock; audit with pip-audit/safety in CI; renovate/dependabot enabled.
- Input validation and output encoding; never eval/exec; subprocess with shell=False and explicit args.
- Least privilege:
  - Drop Linux capabilities in containers; run as non-root UID:GID.
  - Read-only root FS in production; writable only where needed (/tmp, app data).
- Network/HTTP: timeouts and retries; certificate verification on; no disabling SSL checks.
- Data protection: avoid logging PII/secrets; configurable redaction.
- Containers: scan images with Trivy; pin base images by digest; avoid :latest; enable healthcheck.
- Supply chain: generate SBOM (syft) and sign images (cosign) in CI.

## Performance

- Measure first: cProfile, py-spy, scalene; add benchmarks for hot paths.
- Use appropriate concurrency:
  - asyncio/uvloop for IO-bound; threads for blocking IO; processes or native libs for CPU-bound.
- Caching: functools.lru_cache or explicit caches for pure functions; cache DB/HTTP results with sensible TTLs.
- IO/DB: connection pooling, pagination, bulk ops; avoid N+1 queries.
- Code: prefer vectorized libs (numpy/pandas) when suitable; avoid excessive object churn in hot loops; lazy imports where startup matters.
- Docker images: multi-stage builds; slim base; minimize layers; leverage BuildKit cache mounts for pip; no dev deps in prod image.

## Git/Commits

- Conventional Commits: feat|fix|docs|test|refactor|perf|build|ci|chore|revert(scope): message.
- Small, atomic commits; one logical change per commit.
- Branch naming: `feature/<short-desc>`, `fix/<issue-id>-<short>`, `chore/<task>`.
- PRs: concise description, screenshots/logs for UX/behavioral changes; link issues; checklist for tests/docs/notes.
- Use SemVer for releases; tag as vX.Y.Z; update CHANGELOG.

## Requirements Before Each Commit and Pull Request Standard

- Pre-commit passes: ruff (lint + imports), black, mypy, end-of-file-fixer, trailing-whitespace.
- Tests: pytest -q with coverage meeting threshold; no xfails for new code.
- Security: pip-audit (or safety) clean; secret scan clean (detect-secrets or trufflehog).
- Docs: README and relevant docs updated; examples still run.
- Docker: docker build succeeds; image runs basic healthcheck locally.
- No TODO/FIXME left in modified lines unless linked to an issue.
- For breaking changes: bump version, migration notes, deprecation path documented.

## Development Flow

- Trunk-based with short-lived feature branches.
- PR review required; status checks must pass (lint, type, test, security, build).
- CI stages:
  1) Static checks (ruff, black --check, mypy)
  2) Test + coverage
  3) Build Docker image, scan (Trivy), SBOM (syft)
  4) Publish on tag; sign (cosign); push to registry
  5) Deploy to staging; smoke tests; then prod via approval
- Database migrations: forward-only, idempotent; tested on staging before prod; rollback plan documented.
- Feature flags for risky changes; dark launches when possible.

## Repository Structure

```text
.
├── src/your_package/              # Application code (src layout)
│   ├── __init__.py
│   └── ...
├── tests/                         # Pytest suites mirroring src
│   ├── conftest.py
│   └── ...
├── docs/                          # MkDocs/Sphinx (optional)
├── docker/                        # Compose files, auxiliary Docker assets
├── .github/workflows/             # CI pipelines
├── .vscode/                       # Editor settings/tasks (non-secret)
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── pyproject.toml                 # black, ruff, mypy config; builds
├── requirements/                  # If not using pyproject lock:
│   ├── base.in / base.txt
│   ├── dev.in / dev.txt
│   └── prod.txt
├── .env.example
├── .pre-commit-config.yaml
├── CHANGELOG.md
└── README.md
```

## Key Guidelines

- 12-factor app: config via env; stateless processes; logs to stdout/stderr.
- Reproducibility: pinned deps, locked environments, deterministic builds.
- Observability: structured logs, basic metrics, and request tracing hooks (OpenTelemetry ready).
- Backward compatibility: deprecate with warnings and timelines before removal.
- Idempotent scripts and migrations; safe re-runs.
- Fail fast and loudly; prefer explicit over implicit; keep public APIs small and well-documented.
- Keep Docker images minimal; run as non-root; healthcheck endpoints; graceful shutdown (SIGTERM handling).

<!-- markdownlint-enable MD013 -->