Skip to content

Latest commit

 

History

History
212 lines (161 loc) · 10.8 KB

File metadata and controls

212 lines (161 loc) · 10.8 KB

Coding Standards & Quality — Accellens

Version: 1.1 Update Date: January 17, 2025


General Principles

  • SOLID, KISS, DRY, Clean Code.
  • "Code must be understandable by AI": explicit dependencies, readable names, no hidden side effects.
  • Comments in English only and only to explain "why".
  • Update documentation together with functionality.

Python (Backend, Scanners)

  • Python version ≥ 3.13.
  • Package Management: uv (replacing pip and poetry).
  • Linting & Formatting: Ruff (replaces Black, isort, and flake8).
    • Formatting: ruff format (line-length 120).
    • Linting: ruff check (consolidates rule sets).
  • Static analysis: mypy (strict = True), bandit.
  • Docstrings: Google style (mandatory for public classes/functions).
  • Typing: mandatory everywhere, including Celery tasks and background jobs.
  • Async-first: use async def where possible; wrap blocking operations in run_in_executor.
  • Module structure follows the apps/services package (API, services, repositories, schemas) for Python backend and apps/gateway for Node.js API Gateway.

Mypy Rules

  • disallow_untyped_defs = True.
  • warn_unused_ignores = True.
  • Use TypedDict/Protocol instead of dict/Any.
  • Third-party libraries: If a library does not have type stubs (e.g., UnleashClient), use # type: ignore[import-not-found] and wrap calls in strictly typed methods with explicit type casting (e.g., return bool(client.is_enabled(...))).
  • Celery Tasks: Always specify the self: CeleryTask type (from tasks.base.CeleryTask) for decorated functions using bind=True.

Exceptions

  • Only high-level handlers log stacktraces; others propagate exceptions upwards.
  • Override __str__ for domain exceptions so that the UX receives understandable messages.

TypeScript / Frontend

  • TypeScript strict (no implicit any, strictNullChecks, exactOptionalPropertyTypes).
    • Type Safety patterns:
      • For environment variables that might be undefined (like Sentry DSN), always provide a fallback value to ensure string typing: dsn: process.env.SENTRY_DSN || ''.
      • For API client calls using AbortSignal, explicitly handle undefined by coercing to null: { signal: signal ?? null }.
  • ESLint (Airbnb + custom accessibility rules, max-len 120). Additionally, eslint-plugin-jsx-a11y.
  • ESLint Plugins for Code Quality:
    • eslint-plugin-unused-imports: automatically detects and removes unused imports (error).
    • eslint-plugin-sonarjs: detects string duplication (sonarjs/no-duplicate-string, threshold: 3) and high cognitive complexity (sonarjs/cognitive-complexity, threshold: 15).
  • FORBIDDEN to use // eslint-disable to solve linter issues. All ESLint errors must be fixed in the code, not disabled. If an ESLint rule is truly incorrect for a specific case, it must be discussed in a PR and the ESLint configuration updated for the entire project, rather than disabling the rule locally.
  • Prettier (printWidth 120, singleQuote true, trailingComma all).
  • Use React Server Components by default; Client Components only for interactivity.
  • All localization via i18n (en, ru).
  • Use Zustand/TanStack Query for state/data; avoid global singletons.
  • UI components are formed in apps/frontend/src/components and documented in Storybook.

Domain Models and Types

  • ALWAYS use domain models from @accellens/common: Organization, Project, Scan, Finding, OrganizationMemberDto, and others.
  • FORBIDDEN to duplicate domain model definitions in applications (apps/frontend, apps/gateway).
  • Import types directly: import type { Organization, Project } from '@accellens/common'.
  • If UI adapters are needed, use Pick, Omit, or utility types, but do not override base models.
  • This ensures a single source of truth and prevents desynchronization between the frontend and backend.

API Clients and CRUD Operations

  • Use factories from apps/frontend/src/lib/api/factory.ts to create API clients:
    • createCrudApi<TCreate, TUpdate, TEntity>({ basePath }) — for standard CRUD operations.
    • createNestedCrudApi<TParentId, TCreate, TUpdate, TEntity>({ basePath }) — for nested resources (e.g., /projects/:id/scans).
    • buildQueryString(params) — for building query strings with support for arrays and optional parameters.
  • This eliminates code duplication (~150 lines per module) and ensures consistency of API calls.
  • For usage examples, see apps/frontend/src/lib/api/projects.ts, apps/frontend/src/lib/api/scans.ts.

Module Boundaries (Nx)

  • Project Tags:
    • scope:frontend, scope:backend, scope:scanner, scope:ai, scope:simulation, scope:shared.
    • type:app — applications (apps/*), type:lib — libraries (libs/*).
  • Dependency Rules (enforced via @nx/enforce-module-boundaries):
    • type:app can depend only on type:lib.
    • scope:frontend → only scope:frontend and scope:shared libraries.
    • scope:backend → scope:shared, scope:backend, scope:ai, scope:simulation, scope:scanner.
    • scope:scanner → scope:scanner, scope:shared.
    • scope:ai → scope:ai, scope:shared.
    • scope:simulation → scope:simulation, scope:shared.
    • scope:shared → only scope:shared.
  • Any new library/application must receive tags in nx.json, otherwise CI will fail on lint.

Node.js / CLI / Scanners

  • Node.js 24.13.0 LTS (scanners), CLI can be Node/Go — default is Node.js 24.13.0 LTS.
  • Formatting: Prettier + ESLint (typescript-eslint).
  • FORBIDDEN to use // eslint-disable to solve linter issues. All ESLint errors must be fixed in the code, not disabled. If an ESLint rule is truly incorrect for a specific case, it must be discussed in a PR and the ESLint configuration updated for the entire project, rather than disabling the rule locally.
  • CLI commands are documented in api/cli-reference.md.
  • For Playwright, use @playwright/test configs, linting via eslint-plugin-playwright.

Environment Variable Parsing

  • ALWAYS use utilities from @accellens/utils/src/config/env.ts for reading and validating environment variables:
    • readEnvString(key, options) — read string variables with fallback and required support.
    • readEnvNumber(key, options) — read numeric variables with min/max validation.
    • readEnvBoolean(key, options) — read boolean variables.
    • readEnvEnum<T>(key, allowedValues, options) — read enum values with validation.
    • readEnvLogLevel(key, fallback) — read logging level with validation.
  • This ensures uniform configuration error handling, logging, and validation across all services.
  • Usage examples: apps/gateway/src/config/environment.ts, apps/scanner-web/src/config.ts.
  • FORBIDDEN to create your own ENV parsing functions — use the common utilities.

AI / Prompt Engineering

  • Prompts and templates are stored in libs/ai/prompts (YAML/Markdown) with versioning.
  • Each prompt has an owner, version, and application scenario.
  • In tests, use snapshot tests for LLM responses (golden files) with tolerance.
  • Local LLMs (Ollama) — parameterized fallback.

Testing

  • Unit → Integration → E2E (see ../testing/testing.md).
  • Minimum code coverage: backend 80%, frontend 75% (MVP), scanners 70%.
  • Linters and tests must pass in CI before merging.

Smoke Tests for API Schema Validation

  • Smoke tests are mandatory for verifying that API JSON schemas comply with domain models from @accellens/common.
  • Location: tests/smoke/api-schema-validation.test.ts.
  • Run: npm run test:smoke.
  • These tests prevent desynchronization between the API Gateway and domain models:
    • Verify that all mandatory fields of domain models are present in API schemas.
    • Detect missing fields when models change.
    • Ensure architectural type safety.
  • When adding new domain models or changing existing ones, be sure to update the smoke tests.

Git & PR Process

  • Conventional Commits: feat:, fix:, chore:, docs:, refactor:, test:, build:, ci:.
  • PR template includes a checklist for tests, documentation, and security.
  • Mandatory code review by ≥2 engineers or 1 engineer + 1 accessibility specialist.
  • Use feature branches feature/<scope>, bugfix/<issue>, etc.

GitHub API First

  • ✅ ALWAYS use the GitHub API for interacting with GitHub whenever possible!
  • ALWAYS prefer the GitHub API or GitHub CLI (gh) over manual actions through the web interface.
  • ALWAYS use scripts to automate GitHub operations.
  • ALWAYS document GitHub operations via the API in scripts.

Applies to:

  • Updating repository settings (description, topics, website).
  • Creating/updating issues and PRs (when required).
  • Checking workflow and run statuses.
  • Getting repository information.
  • Managing labels, milestones, and projects.

Tools:

  • GitHub CLI (gh) — recommended for most operations.
  • GitHub API directly (curl, Python requests) — for complex operations.
  • Scripts in scripts/ — for automating repetitive tasks.

More details in developer-guide.md#111-utilities-and-scripts.


Security

  • Secrets only in Vault/KMS; .env is stored locally or in a secrets manager.
  • No PII in logs; use redaction utilities.
  • Enable dependency scanning (poetry lock audit, npm audit, trivy).
  • Access tokens and keys are rotated every 30 days (configurable).

Pre-merge Checks

  1. npm run lint (includes validate:nx-tags and verification of all projects via Nx).
  2. npm run test (unit + integration subset).
  3. npm run test:smoke (API schema validation against domain models).
  4. npm run build (containers) — nightly.
  5. Updated documentation and changelog.
  6. Accessibility check (axe, pa11y) for modified UI.

Automated Quality Checks

  • ESLint with plugins automatically detects:
    • Unused imports (unused-imports/no-unused-imports).
    • String duplication (sonarjs/no-duplicate-string).
    • High cognitive complexity (sonarjs/cognitive-complexity).
  • SonarQube/SonarCloud performs centralized code quality analysis:
  • Nx module boundaries checks compliance with architectural boundaries between projects.
  • Smoke tests verify API schema compliance with domain models.
  • All checks must pass before creating a PR.