feat(rules): add shared development and security rules

This commit is contained in:
Julian lechner
2026-09-11 14:42:29 +02:00
parent 25bc29b8a4
commit 8b5a7e39b3
12 changed files with 2169 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
# TypeScript Code Guidelines
* Write clear, readable, maintainable code first.
* Prefer modern TypeScript and current ECMAScript syntax.
* Keep code simple and explicit.
* Avoid clever or overly abstract solutions.
* Follow the existing project style and architecture.
* Enable strict TypeScript settings where possible.
* Prefer `strict: true`.
* Avoid `any`.
* Prefer precise types over broad types.
* Prefer `unknown` over `any` for untrusted or unknown values.
* Narrow types explicitly before use.
* Prefer strongly typed models over loose objects.
* Avoid excessive type assertions.
* Avoid non-null assertions unless safety is guaranteed.
* Prefer discriminated unions for state and variant modeling.
* Prefer literal unions over arbitrary strings.
* Prefer enums only when they provide a clear benefit.
* Prefer `readonly` where mutation is not required.
* Prefer immutable data where practical.
* Avoid unnecessary mutation.
* Avoid global mutable state.
* Keep functions small and focused.
* Keep modules focused on a clear responsibility.
* Prefer composition over inheritance.
* Avoid unnecessary classes when functions and plain objects are sufficient.
* Avoid unnecessary interfaces and abstractions.
* Prefer concrete object types when no abstraction is required.
* Use interfaces primarily when extension, implementation contracts, or declaration merging is actually useful.
* Prefer `type` aliases for unions, compositions, mapped types, and local data models.
* Avoid unnecessary wrapper types.
* Avoid excessive generic complexity.
* Keep generic constraints explicit and meaningful.
* Avoid deeply nested conditional or mapped types unless they provide clear value.
* Prefer readable types over type-system cleverness.
* Avoid duplicated type definitions.
* Derive types from existing sources when practical.
* Do not duplicate backend contracts manually when generated or shared types are available.
* Prefer explicit return types for public APIs and non-trivial functions.
* Prefer inference for simple local variables.
* Avoid unnecessary annotations when inference is obvious.
* Prefer `const` by default.
* Use `let` only when reassignment is required.
* Avoid `var`.
* Prefer optional chaining and nullish coalescing where appropriate.
* Do not use `||` when `0`, `false`, or empty strings are valid values.
* Handle `null` and `undefined` intentionally.
* Avoid mixing `null` and `undefined` without a clear convention.
* Prefer early returns over excessive nesting.
* Avoid deeply nested control flow.
* Avoid overly large functions.
* Avoid hidden side effects.
* Keep pure logic pure where practical.
* Prefer deterministic behavior.
* Avoid implicit runtime coercion.
* Use strict equality.
* Avoid unnecessary object spreading in hot paths.
* Avoid unnecessary array copies.
* Avoid unnecessary intermediate arrays.
* Avoid repeated `.map()`, `.filter()`, or `.reduce()` chains in performance-critical paths.
* Use array methods when they improve readability and performance is not critical.
* Prefer appropriate data structures such as `Map` and `Set` when lookup behavior requires them.
* Avoid O(n²) patterns when a better structure is practical.
* Measure performance before micro-optimizing.
* Avoid unnecessary JSON serialization and parsing.
* Avoid unnecessary deep cloning.
* Avoid `JSON.parse(JSON.stringify(...))` as a cloning strategy.
* Prefer platform APIs such as `structuredClone` when deep cloning is actually required.
* Avoid synchronous blocking operations in server-side hot paths.
* Prefer asynchronous APIs for I/O.
* Always handle rejected promises.
* Avoid floating promises.
* Use `await` when sequencing is required.
* Use `Promise.all` for independent operations when safe.
* Limit concurrency for large workloads.
* Avoid uncontrolled `Promise.all` over very large collections.
* Support cancellation with `AbortSignal` where applicable.
* Clean up event listeners, timers, subscriptions, streams, and resources.
* Avoid memory leaks caused by retained closures or listeners.
* Do not swallow exceptions.
* Preserve useful error context.
* Use typed domain errors where they improve handling.
* Avoid exceptions for normal control flow.
* Validate external input at system boundaries.
* Never trust API payloads, query parameters, environment variables, storage data, or user input based solely on TypeScript types.
* Use runtime validation for untrusted external data.
* Do not assume compile-time types provide runtime safety.
* Prefer schema validation when external contracts are complex.
* Never expose secrets, tokens, credentials, or sensitive data.
* Do not log sensitive information.
* Avoid unsafe dynamic property access.
* Avoid `eval`, `Function`, and dynamic code execution.
* Avoid unsafe HTML injection.
* Sanitize untrusted HTML when rendering HTML is required.
* Avoid weakening TLS, authentication, authorization, CSP, validation, or other security controls.
* Treat all external data as untrusted.
* Prefer secure defaults.
* Do not disable security checks for convenience.
* Avoid prototype pollution risks when merging untrusted objects.
* Prefer allowlists over denylists for security-sensitive validation.
* Keep dependencies minimal.
* Prefer built-in platform APIs over adding small utility dependencies.
* Do not add dependencies without a clear reason.
* Avoid abandoned or unnecessary packages.
* Keep dependencies current and supported.
* Respect lockfiles.
* Do not manually modify generated lockfile content.
* Avoid broad dependency upgrades unrelated to the task.
* Use ESM or the project's existing module system consistently.
* Avoid mixing module systems without necessity.
* Prefer named exports unless the project convention favors default exports.
* Keep import paths consistent.
* Remove unused imports and exports.
* Avoid circular dependencies.
* Keep frontend, domain, application, and infrastructure concerns separated where applicable.
* Keep API and transport models separate from domain logic when necessary.
* Do not leak implementation details through public APIs.
* Avoid unnecessary public exports.
* Keep module boundaries intentional.
* Write code that is easy to test.
* Prefer behavior-based tests.
* Avoid tests coupled to implementation details.
* Mock only external boundaries or expensive dependencies where practical.
* Keep tests deterministic.
* Avoid time-, network-, and environment-dependent tests without proper isolation.
* Remove dead code instead of keeping it as commented-out code.
* Do not add comments unless the user explicitly requests them.
* Use descriptive naming.
* Avoid vague names such as `data`, `obj`, `item`, `temp`, or `value` when more precise names are available.
* Avoid abbreviations unless they are established domain terminology.
* Keep naming conventions consistent.
* Treat lint and TypeScript errors seriously.
* Do not suppress ESLint or TypeScript diagnostics without a concrete reason.
* Avoid `@ts-ignore`.
* Prefer `@ts-expect-error` only when the error is intentional and documented.
* Do not disable lint rules globally for local problems.
* Prefer correctness, security, maintainability, and predictable behavior over micro-optimizations.
## Performance Priority
Prioritize performance work in this order:
* Architecture
* Network and API usage
* Database access
* Algorithms and data structures
* Rendering and state updates
* Concurrency
* Memory allocations
* CPU micro-optimizations
Never optimize based purely on assumptions.
## Safety Rule
* Compile-time type safety is not runtime validation.
* Validate all external and untrusted data.
* Do not use `any`, type assertions, non-null assertions, or disabled compiler checks to bypass real type problems.
* Prefer making invalid states unrepresentable where practical.