Version: 1.1 Update Date: January 17, 2025
- SOLID, KISS, DRY, Clean Code.
- More details:
docs/development/solid-principles.md(Note: verify if these exist or are placeholders) - More details:
docs/development/design-patterns.md
- More details:
- "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 version ≥ 3.13.
- Package Management:
uv(replacingpipandpoetry). - Linting & Formatting:
Ruff(replaces Black, isort, and flake8).- Formatting:
ruff format(line-length 120). - Linting:
ruff check(consolidates rule sets).
- Formatting:
- 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 defwhere possible; wrap blocking operations inrun_in_executor. - Module structure follows the
apps/servicespackage (API, services, repositories, schemas) for Python backend andapps/gatewayfor Node.js API Gateway.
disallow_untyped_defs = True.warn_unused_ignores = True.- Use
TypedDict/Protocolinstead ofdict/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: CeleryTasktype (fromtasks.base.CeleryTask) for decorated functions usingbind=True.
- Only high-level handlers log stacktraces; others propagate exceptions upwards.
- Override
__str__for domain exceptions so that the UX receives understandable messages.
- 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 handleundefinedby coercing tonull:{ signal: signal ?? null }.
- For environment variables that might be undefined (like Sentry DSN), always provide a fallback value to ensure string typing:
- Type Safety patterns:
- 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-disableto 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/componentsand documented in Storybook.
- 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.
- Use factories from
apps/frontend/src/lib/api/factory.tsto 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.
- 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:appcan depend only ontype:lib.scope:frontend→ onlyscope:frontendandscope:sharedlibraries.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→ onlyscope:shared.
- Any new library/application must receive tags in
nx.json, otherwise CI will fail on lint.
- 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-disableto 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/testconfigs, linting viaeslint-plugin-playwright.
- ALWAYS use utilities from
@accellens/utils/src/config/env.tsfor 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.
- 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.
- 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 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.
- 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.
- ✅ 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, Pythonrequests) — for complex operations. - Scripts in
scripts/— for automating repetitive tasks.
More details in developer-guide.md#111-utilities-and-scripts.
- Secrets only in Vault/KMS;
.envis 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).
npm run lint(includesvalidate:nx-tagsand verification of all projects via Nx).npm run test(unit + integration subset).npm run test:smoke(API schema validation against domain models).npm run build(containers) — nightly.- Updated documentation and changelog.
- Accessibility check (axe, pa11y) for modified UI.
- ESLint with plugins automatically detects:
- Unused imports (
unused-imports/no-unused-imports). - String duplication (
sonarjs/no-duplicate-string). - High cognitive complexity (
sonarjs/cognitive-complexity).
- Unused imports (
- SonarQube/SonarCloud performs centralized code quality analysis:
- Coverage: backend ≥80%, frontend ≥75%.
- Code smells, bugs, security vulnerabilities.
- Technical debt tracking.
- Quality gates to block merging on low quality.
- More details:
sonarqube-setup.md,sonarqube-quality-gates.md,sonarqube-results-interpretation.md.
- 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.