feat(rules): add shared development and security rules
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
# Angular Code Guidelines
|
||||
|
||||
* Use modern Angular patterns and current framework conventions.
|
||||
* Prefer standalone components, directives and pipes for new code.
|
||||
* Avoid introducing `NgModule` unless the existing project architecture requires it.
|
||||
* Keep components small and focused.
|
||||
* Keep templates simple.
|
||||
* Move complex logic out of templates.
|
||||
* Keep business logic out of components where practical.
|
||||
* Prefer services, facades or dedicated domain logic for non-trivial behavior.
|
||||
* Avoid god components and god services.
|
||||
* Keep dependencies explicit.
|
||||
* Prefer composition over inheritance.
|
||||
* Avoid unnecessary abstractions.
|
||||
* Avoid unnecessary wrapper components.
|
||||
* Follow the existing project architecture unless there is a strong reason to change it.
|
||||
|
||||
## Components
|
||||
|
||||
* Use `ChangeDetectionStrategy.OnPush` unless there is a concrete reason not to.
|
||||
* Prefer signal-based state for local component state.
|
||||
* Prefer `computed` for derived state.
|
||||
* Prefer `effect` only for actual side effects.
|
||||
* Do not use `effect` as a replacement for normal data flow.
|
||||
* Keep component state minimal.
|
||||
* Avoid duplicating derived state.
|
||||
* Prefer immutable state updates.
|
||||
* Avoid direct mutation of shared state.
|
||||
* Keep inputs and outputs strongly typed.
|
||||
* Prefer signal-based inputs and outputs when consistent with the project.
|
||||
* Avoid unnecessary two-way binding.
|
||||
* Avoid unnecessary component-to-component coupling.
|
||||
* Prefer explicit data flow from parent to child and explicit events upward.
|
||||
* Do not expose internal component state unnecessarily.
|
||||
* Use lifecycle hooks only when required.
|
||||
* Avoid complex initialization logic inside constructors.
|
||||
|
||||
## Templates
|
||||
|
||||
* Keep expressions short and readable.
|
||||
* Do not execute expensive methods from templates.
|
||||
* Avoid function calls in templates when their result can be derived or cached.
|
||||
* Avoid complex conditions directly in markup.
|
||||
* Prefer derived state in TypeScript over repeated template expressions.
|
||||
* Use Angular control flow syntax such as `@if`, `@for` and `@switch` for new code.
|
||||
* Always provide stable tracking for repeated collections.
|
||||
* Avoid deeply nested template structures.
|
||||
* Split large templates into focused components when it improves maintainability.
|
||||
* Avoid unnecessary DOM elements.
|
||||
* Use semantic HTML.
|
||||
* Prefer native HTML behavior before custom implementations.
|
||||
* Keep accessibility in mind when choosing elements and interactions.
|
||||
|
||||
## Signals and State
|
||||
|
||||
* Prefer signals for local and synchronous reactive state.
|
||||
* Prefer `computed` for derived values.
|
||||
* Keep signals private when external mutation is not intended.
|
||||
* Expose readonly state where practical.
|
||||
* Avoid storing values that can be derived from existing state.
|
||||
* Avoid circular signal dependencies.
|
||||
* Avoid side effects inside `computed`.
|
||||
* Keep effects small and deterministic.
|
||||
* Clean up resources created by effects.
|
||||
* Do not use global state unless multiple unrelated parts of the application genuinely need it.
|
||||
* Do not introduce a state-management library without a clear requirement.
|
||||
|
||||
## RxJS
|
||||
|
||||
* Use RxJS for asynchronous streams, events and complex reactive flows.
|
||||
* Do not use RxJS when simple synchronous signals are sufficient.
|
||||
* Prefer declarative observable pipelines.
|
||||
* Avoid nested `subscribe`.
|
||||
* Avoid manual subscriptions where `async`, signals or framework helpers are sufficient.
|
||||
* Prefer `takeUntilDestroyed` or equivalent Angular lifecycle integration for manual subscriptions.
|
||||
* Always consider subscription lifetime.
|
||||
* Avoid memory leaks from unmanaged subscriptions.
|
||||
* Use the correct flattening operator for the required semantics.
|
||||
* Do not use `switchMap`, `mergeMap`, `concatMap` or `exhaustMap` interchangeably.
|
||||
* Avoid unnecessary `Subject` usage.
|
||||
* Prefer exposing observables instead of exposing mutable subjects.
|
||||
* Prefer `BehaviorSubject` only when a current value is actually required.
|
||||
* Avoid excessive observable chains for simple state.
|
||||
* Avoid converting repeatedly between signals and observables without need.
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
* Prefer Angular dependency injection for application services.
|
||||
* Keep injected dependencies minimal.
|
||||
* Avoid service locator patterns.
|
||||
* Prefer `inject()` where it improves readability and is consistent with the project.
|
||||
* Do not inject services that are not used.
|
||||
* Scope services intentionally.
|
||||
* Prefer application-wide singletons only for truly shared stateless or coordinated state.
|
||||
* Avoid storing request-specific or component-specific mutable state in root services.
|
||||
* Use injection tokens for configuration or abstractions where appropriate.
|
||||
* Do not create interfaces only to satisfy dependency injection when no abstraction is needed.
|
||||
|
||||
## Services
|
||||
|
||||
* Keep services focused on a clear responsibility.
|
||||
* Avoid large catch-all services.
|
||||
* Separate API access, domain logic and UI state where practical.
|
||||
* Avoid leaking transport models throughout the application.
|
||||
* Do not expose mutable internal state directly.
|
||||
* Prefer readonly APIs for state consumers.
|
||||
* Avoid hidden side effects.
|
||||
* Keep service methods predictable.
|
||||
* Do not use services merely to move poorly structured component code elsewhere.
|
||||
|
||||
## HTTP and APIs
|
||||
|
||||
* Keep API access centralized and strongly typed.
|
||||
* Prefer dedicated API clients or data-access services.
|
||||
* Do not use `any` for API responses.
|
||||
* Treat all server responses as untrusted at runtime.
|
||||
* Validate external data when the contract is security- or correctness-critical.
|
||||
* Keep DTOs separate from domain models when their responsibilities differ.
|
||||
* Avoid duplicate API calls.
|
||||
* Cache only when the invalidation strategy is clear.
|
||||
* Avoid manual URL string construction when typed helpers or centralized endpoints are available.
|
||||
* Use interceptors only for cross-cutting concerns.
|
||||
* Do not put unrelated business logic into HTTP interceptors.
|
||||
* Handle cancellation where appropriate.
|
||||
* Handle expected error states explicitly.
|
||||
|
||||
## Forms
|
||||
|
||||
* Prefer reactive forms for non-trivial forms.
|
||||
* Keep forms strongly typed.
|
||||
* Avoid untyped forms.
|
||||
* Keep validation rules centralized and reusable where practical.
|
||||
* Validate on both client and server where required.
|
||||
* Never treat client-side validation as a security boundary.
|
||||
* Keep form state separate from domain state when useful.
|
||||
* Avoid large components that combine layout, validation, persistence and business logic.
|
||||
* Display validation errors consistently.
|
||||
* Preserve user input when recoverable errors occur.
|
||||
|
||||
## Routing
|
||||
|
||||
* Keep route definitions explicit and predictable.
|
||||
* Prefer lazy loading for larger feature areas.
|
||||
* Avoid loading large feature bundles eagerly without need.
|
||||
* Use route guards only for navigation behavior, not as a security boundary.
|
||||
* Authorization must still be enforced on the backend.
|
||||
* Keep resolvers focused.
|
||||
* Avoid expensive work during navigation unless required.
|
||||
* Keep route parameters strongly typed at application boundaries where practical.
|
||||
* Do not rely on client-side routing state for sensitive authorization decisions.
|
||||
|
||||
## Performance
|
||||
|
||||
* Use `OnPush`.
|
||||
* Use stable tracking in loops.
|
||||
* Avoid unnecessary change detection triggers.
|
||||
* Avoid repeated expensive template calculations.
|
||||
* Avoid unnecessary subscriptions.
|
||||
* Avoid unnecessary DOM rendering.
|
||||
* Lazy-load large features and heavy dependencies where appropriate.
|
||||
* Avoid large initial bundles.
|
||||
* Avoid importing full libraries when only a small part is required.
|
||||
* Avoid unnecessary deep cloning.
|
||||
* Avoid unnecessary object and array recreation in hot paths.
|
||||
* Keep state updates targeted.
|
||||
* Avoid unnecessary global state updates.
|
||||
* Measure bundle size and runtime performance before micro-optimizing.
|
||||
* Prefer architectural improvements over template-level micro-optimizations.
|
||||
|
||||
## Security
|
||||
|
||||
* Treat all external data as untrusted.
|
||||
* Never bypass Angular sanitization without a verified reason.
|
||||
* Avoid direct DOM manipulation.
|
||||
* Avoid `innerHTML` with untrusted content.
|
||||
* Avoid `bypassSecurityTrust*` unless explicitly required and the input is fully controlled.
|
||||
* Never expose secrets in frontend code.
|
||||
* Never store sensitive credentials in the Angular application.
|
||||
* Do not rely on frontend checks for authorization.
|
||||
* Enforce authentication and authorization on the backend.
|
||||
* Avoid leaking sensitive information through logs or error messages.
|
||||
* Use secure cookie or token handling according to the application's authentication architecture.
|
||||
* Avoid storing sensitive tokens in insecure browser storage without a deliberate security decision.
|
||||
* Do not disable security controls for convenience.
|
||||
|
||||
## DOM and Browser APIs
|
||||
|
||||
* Prefer Angular APIs and declarative templates over direct DOM manipulation.
|
||||
* Use `Renderer2` only when direct rendering abstraction is actually needed.
|
||||
* Avoid accessing globals directly when it harms testability or SSR compatibility.
|
||||
* Consider SSR and hydration compatibility for browser-specific code.
|
||||
* Guard access to `window`, `document`, `localStorage` and similar browser-only APIs when SSR is supported.
|
||||
* Clean up event listeners, observers and timers.
|
||||
* Avoid layout thrashing in performance-sensitive code.
|
||||
|
||||
## Accessibility
|
||||
|
||||
* Use semantic HTML.
|
||||
* Preserve keyboard navigation.
|
||||
* Ensure interactive elements are actually interactive elements.
|
||||
* Do not replace buttons with clickable `div` elements.
|
||||
* Provide labels for form controls.
|
||||
* Maintain visible focus behavior.
|
||||
* Use ARIA only when native HTML semantics are insufficient.
|
||||
* Avoid unnecessary custom widgets.
|
||||
* Keep accessible names and states synchronized with UI state.
|
||||
|
||||
## Styling
|
||||
|
||||
* Keep styles scoped and predictable.
|
||||
* Avoid unnecessary global CSS.
|
||||
* Follow the project's styling strategy consistently.
|
||||
* Avoid excessive specificity.
|
||||
* Avoid `!important` unless there is a concrete reason.
|
||||
* Prefer reusable design tokens and shared styles over duplicated magic values.
|
||||
* Keep component styles focused on component concerns.
|
||||
* Avoid styling based on fragile DOM structure.
|
||||
* Do not mix multiple styling approaches without need.
|
||||
|
||||
## Testing
|
||||
|
||||
* Test behavior, not implementation details.
|
||||
* Prefer focused component tests.
|
||||
* Test critical user interactions.
|
||||
* Test services and domain logic independently where useful.
|
||||
* Avoid brittle tests coupled to internal structure.
|
||||
* Avoid excessive mocking.
|
||||
* Mock external boundaries rather than internal implementation details.
|
||||
* Keep tests deterministic.
|
||||
* Avoid time-dependent tests without controlled clocks.
|
||||
* Avoid network-dependent tests without proper isolation.
|
||||
* Keep test setup minimal and readable.
|
||||
* Update tests when refactoring changes structure but not behavior.
|
||||
|
||||
## Architecture
|
||||
|
||||
* Keep UI, application, domain and data-access concerns separated where practical.
|
||||
* Organize code by feature rather than by technical file type when it improves cohesion.
|
||||
* Avoid circular dependencies.
|
||||
* Avoid cross-feature imports without a clear contract.
|
||||
* Keep shared code genuinely shared.
|
||||
* Do not move feature-specific logic into generic shared modules.
|
||||
* Avoid dumping unrelated helpers into global utility files.
|
||||
* Keep public APIs of feature areas small.
|
||||
* Avoid exposing internal implementation details across feature boundaries.
|
||||
* Prefer local ownership of state and logic.
|
||||
|
||||
## Code Quality
|
||||
|
||||
* Use strict TypeScript settings.
|
||||
* Avoid `any`.
|
||||
* Avoid unnecessary type assertions.
|
||||
* Avoid non-null assertions unless safety is guaranteed.
|
||||
* Prefer modern, readable syntax.
|
||||
* Use descriptive names.
|
||||
* Avoid vague names such as `data`, `item`, `value` or `temp` when better names exist.
|
||||
* Remove dead code.
|
||||
* Remove unused imports and dependencies.
|
||||
* Remove commented-out code instead of keeping it in source files.
|
||||
* Do not add comments unless the user explicitly requests them.
|
||||
* Treat Angular, TypeScript and lint warnings seriously.
|
||||
* Do not suppress diagnostics without a concrete reason.
|
||||
* Prefer correctness, security and maintainability over cleverness.
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
* Prefer Angular and browser platform capabilities before adding third-party libraries.
|
||||
* Do not add dependencies without a clear benefit.
|
||||
* Avoid libraries that duplicate existing framework functionality.
|
||||
* Avoid abandoned or poorly maintained packages.
|
||||
* Keep Angular package versions aligned.
|
||||
* Do not mix incompatible Angular package versions.
|
||||
* Respect the existing lockfile and package manager.
|
||||
* Avoid unrelated dependency upgrades.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize Angular performance work in this order:
|
||||
|
||||
* Application architecture
|
||||
* Network and API behavior
|
||||
* Bundle size and lazy loading
|
||||
* State architecture
|
||||
* Change detection
|
||||
* Rendering and DOM complexity
|
||||
* RxJS and subscription behavior
|
||||
* Memory allocations
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
* Angular frontend code is never a security boundary.
|
||||
* Client-side validation, guards, hidden controls and disabled UI elements do not replace backend enforcement.
|
||||
* Do not bypass Angular's built-in security mechanisms without a verified and explicit reason.
|
||||
* Prefer safe framework defaults over custom low-level behavior.
|
||||
Reference in New Issue
Block a user