testing ADR - architectural decisions
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 14m37s
All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 14m37s
This commit is contained in:
@@ -31,13 +31,13 @@ We will adopt a strict, consistent error-handling contract for the service and r
|
||||
|
||||
### Positive
|
||||
|
||||
* **Robustness**: Eliminates an entire class of bugs where `undefined` is passed to `res.json()`, preventing incorrect `500` errors.
|
||||
* **Consistency & Predictability**: All data-fetching methods now have a predictable contract. They either return the expected data or throw a specific, typed error.
|
||||
* **Developer Experience**: Route handlers become simpler, cleaner, and easier to write correctly. The cognitive load on developers is reduced as they no longer need to remember to check for `undefined`.
|
||||
* **Improved Testability**: Tests become more reliable and realistic. Mocks can now throw the *exact* error type (`new NotFoundError()`) that the real implementation would, ensuring tests accurately reflect the application's behavior.
|
||||
* **Centralized Control**: Error-to-HTTP-status logic is centralized in the `errorHandler` middleware, making it easy to manage and modify error responses globally.
|
||||
**Robustness**: Eliminates an entire class of bugs where `undefined` is passed to `res.json()`, preventing incorrect `500` errors.
|
||||
**Consistency & Predictability**: All data-fetching methods now have a predictable contract. They either return the expected data or throw a specific, typed error.
|
||||
**Developer Experience**: Route handlers become simpler, cleaner, and easier to write correctly. The cognitive load on developers is reduced as they no longer need to remember to check for `undefined`.
|
||||
**Improved Testability**: Tests become more reliable and realistic. Mocks can now throw the *exact* error type (`new NotFoundError()`) that the real implementation would, ensuring tests accurately reflect the application's behavior.
|
||||
**Centralized Control**: Error-to-HTTP-status logic is centralized in the `errorHandler` middleware, making it easy to manage and modify error responses globally.
|
||||
|
||||
### Negative
|
||||
|
||||
* **Initial Refactoring**: Requires a one-time effort to audit and refactor all existing repository methods to conform to this new standard.
|
||||
* **Convention Adherence**: Developers must be aware of and adhere to this convention. This ADR serves as the primary documentation for this pattern.
|
||||
**Initial Refactoring**: Requires a one-time effort to audit and refactor all existing repository methods to conform to this new standard.
|
||||
**Convention Adherence**: Developers must be aware of and adhere to this convention. This ADR serves as the primary documentation for this pattern.
|
||||
@@ -18,9 +18,9 @@ This manual approach has several drawbacks:
|
||||
We will implement a standardized "Unit of Work" pattern through a high-level `withTransaction` helper function. This function will abstract away the complexity of transaction management.
|
||||
|
||||
1. **`withTransaction` Helper**: A new helper function, `withTransaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T>`, will be created. This function will be responsible for:
|
||||
* Acquiring a client from the database pool.
|
||||
* Starting a transaction (`BEGIN`).
|
||||
* Executing the `callback` function, passing the transactional client to it.
|
||||
* Acquiring a client from the database pool.
|
||||
* Starting a transaction (`BEGIN`).
|
||||
* Executing the `callback` function, passing the transactional client to it.
|
||||
* If the callback succeeds, it will `COMMIT` the transaction.
|
||||
* If the callback throws an error, it will `ROLLBACK` the transaction and re-throw the error.
|
||||
* In all cases, it will `RELEASE` the client back to the pool.
|
||||
@@ -51,12 +51,12 @@ async function registerUserAndCreateDefaultList(userData) {
|
||||
|
||||
### Positive
|
||||
|
||||
* **DRY (Don't Repeat Yourself)**: Transaction logic is defined in one place, eliminating boilerplate from repository and service files.
|
||||
* **Safety and Reliability**: Guarantees that clients are always released, preventing connection leaks. Ensures proper rollback on any error.
|
||||
* **Clear Composability**: Provides a clear and explicit pattern for composing multiple database operations into a single atomic unit.
|
||||
* **Improved Readability**: Service logic becomes cleaner, focusing on the business operations rather than the mechanics of transaction management.
|
||||
**DRY (Don't Repeat Yourself)**: Transaction logic is defined in one place, eliminating boilerplate from repository and service files.
|
||||
**Safety and Reliability**: Guarantees that clients are always released, preventing connection leaks. Ensures proper rollback on any error.
|
||||
**Clear Composability**: Provides a clear and explicit pattern for composing multiple database operations into a single atomic unit.
|
||||
**Improved Readability**: Service logic becomes cleaner, focusing on the business operations rather than the mechanics of transaction management.
|
||||
|
||||
### Negative
|
||||
|
||||
* **Learning Curve**: Developers will need to learn and adopt the `withTransaction` pattern for all transactional database work.
|
||||
* **Refactoring Effort**: Existing methods that manually manage transactions (`createUser`, `createBudget`, etc.) will need to be refactored to use the new pattern.
|
||||
**Learning Curve**: Developers will need to learn and adopt the `withTransaction` pattern for all transactional database work.
|
||||
**Refactoring Effort**: Existing methods that manually manage transactions (`createUser`, `createBudget`, etc.) will need to be refactored to use the new pattern.
|
||||
|
||||
@@ -57,14 +57,14 @@ router.get('/:id', validateRequest(getFlyerSchema), async (req, res, next) => {
|
||||
|
||||
### Positive
|
||||
|
||||
* **DRY and Declarative**: Validation logic is defined once in a schema and removed from route handlers.
|
||||
* **Improved Readability**: Route handlers become much cleaner and focus exclusively on their core business logic.
|
||||
* **Type Safety**: `zod` schemas provide strong compile-time and runtime type safety, reducing bugs.
|
||||
* **Consistent and Detailed Errors**: The `errorHandler` can be configured to provide consistent, detailed validation error messages for all routes (e.g., "Query parameter 'limit' must be a positive integer").
|
||||
* **Robustness**: Prevents invalid data from ever reaching the service or database layers.
|
||||
**DRY and Declarative**: Validation logic is defined once in a schema and removed from route handlers.
|
||||
**Improved Readability**: Route handlers become much cleaner and focus exclusively on their core business logic.
|
||||
**Type Safety**: `zod` schemas provide strong compile-time and runtime type safety, reducing bugs.
|
||||
**Consistent and Detailed Errors**: The `errorHandler` can be configured to provide consistent, detailed validation error messages for all routes (e.g., "Query parameter 'limit' must be a positive integer").
|
||||
**Robustness**: Prevents invalid data from ever reaching the service or database layers.
|
||||
|
||||
### Negative
|
||||
|
||||
* **New Dependency**: Introduces `zod` as a new project dependency.
|
||||
* **Learning Curve**: Developers need to learn the `zod` schema definition syntax.
|
||||
* **Refactoring Effort**: Requires a one-time effort to create schemas and refactor all existing routes to use the `validateRequest` middleware.
|
||||
**New Dependency**: Introduces `zod` as a new project dependency.
|
||||
**Learning Curve**: Developers need to learn the `zod` schema definition syntax.
|
||||
**Refactoring Effort**: Requires a one-time effort to create schemas and refactor all existing routes to use the `validateRequest` middleware.
|
||||
@@ -9,31 +9,31 @@
|
||||
Our application currently uses a `logger` service, but the implementation of logging varies significantly across different modules. The `errorHandler` middleware produces high-quality, structured JSON logs for errors, but logging within route handlers and service layers is often ad-hoc, using plain strings or inconsistent object structures.
|
||||
|
||||
This inconsistency leads to several problems:
|
||||
1. **Difficult Debugging**: It is hard to trace a single user request through the system or correlate events related to a specific operation.
|
||||
2. **Ineffective Log Analysis**: Inconsistent log formats make it difficult to effectively query, filter, and create dashboards in a log management system (like Datadog, Splunk, or the ELK stack).
|
||||
3. **Security Risks**: There is no enforced standard for redacting sensitive information (like passwords or tokens) in logs outside of the `errorHandler`, increasing the risk of accidental data exposure.
|
||||
4. **Missing Context**: Logs often lack crucial context, such as a unique request ID, the authenticated user's ID, or the source IP address, making them less useful for diagnosing issues.
|
||||
**Difficult Debugging**: It is hard to trace a single user request through the system or correlate events related to a specific operation.
|
||||
**Ineffective Log Analysis**: Inconsistent log formats make it difficult to effectively query, filter, and create dashboards in a log management system (like Datadog, Splunk, or the ELK stack).
|
||||
**Security Risks**: There is no enforced standard for redacting sensitive information (like passwords or tokens) in logs outside of the `errorHandler`, increasing the risk of accidental data exposure.
|
||||
**Missing Context**: Logs often lack crucial context, such as a unique request ID, the authenticated user's ID, or the source IP address, making them less useful for diagnosing issues.
|
||||
|
||||
## Decision
|
||||
|
||||
We will adopt a standardized, application-wide structured logging policy. All log entries MUST be in JSON format and adhere to a consistent schema.
|
||||
|
||||
1. **Request-Scoped Logger with Context**: We will create a middleware that runs at the beginning of the request lifecycle. This middleware will:
|
||||
* Generate a unique `request_id` for each incoming request.
|
||||
* Create a request-scoped logger instance (a "child logger") that automatically includes the `request_id`, `user_id` (if authenticated), and `ip_address` in every log message it generates.
|
||||
* Attach this child logger to the `req` object (e.g., `req.log`).
|
||||
**Request-Scoped Logger with Context**: We will create a middleware that runs at the beginning of the request lifecycle. This middleware will:
|
||||
* Generate a unique `request_id` for each incoming request.
|
||||
* Create a request-scoped logger instance (a "child logger") that automatically includes the `request_id`, `user_id` (if authenticated), and `ip_address` in every log message it generates.
|
||||
* Attach this child logger to the `req` object (e.g., `req.log`).
|
||||
|
||||
2. **Mandatory Use of Request-Scoped Logger**: All route handlers and any service functions called by them **MUST** use the request-scoped logger (`req.log`) instead of the global logger instance. This ensures all logs for a given request are automatically correlated.
|
||||
**Mandatory Use of Request-Scoped Logger**: All route handlers and any service functions called by them **MUST** use the request-scoped logger (`req.log`) instead of the global logger instance. This ensures all logs for a given request are automatically correlated.
|
||||
|
||||
3. **Standardized Log Schema**: All log messages should follow a base schema. The logger configuration will be updated to enforce this.
|
||||
* **Base Fields**: `level`, `timestamp`, `message`, `request_id`, `user_id`, `ip_address`.
|
||||
* **Error Fields**: When logging an error, the log entry MUST include an `error` object with `name`, `message`, and `stack`.
|
||||
**Standardized Log Schema**: All log messages should follow a base schema. The logger configuration will be updated to enforce this.
|
||||
**Base Fields**: `level`, `timestamp`, `message`, `request_id`, `user_id`, `ip_address`.
|
||||
**Error Fields**: When logging an error, the log entry MUST include an `error` object with `name`, `message`, and `stack`.
|
||||
|
||||
4. **Standardized Logging Practices**:
|
||||
* **INFO**: Log key business events, such as `User logged in` or `Flyer processed`.
|
||||
* **WARN**: Log recoverable errors or unusual situations that do not break the request, such as `Client Error: 404 on GET /api/non-existent-route` or `Retrying failed database connection`.
|
||||
* **ERROR**: Log only unhandled or server-side errors that cause a request to fail (typically handled by the `errorHandler`). Avoid logging expected client errors (like 4xx) at this level.
|
||||
* **DEBUG**: Log detailed diagnostic information useful during development, such as function entry/exit points or variable states.
|
||||
**Standardized Logging Practices**:
|
||||
**INFO**: Log key business events, such as `User logged in` or `Flyer processed`.
|
||||
**WARN**: Log recoverable errors or unusual situations that do not break the request, such as `Client Error: 404 on GET /api/non-existent-route` or `Retrying failed database connection`.
|
||||
**ERROR**: Log only unhandled or server-side errors that cause a request to fail (typically handled by the `errorHandler`). Avoid logging expected client errors (like 4xx) at this level.
|
||||
**DEBUG**: Log detailed diagnostic information useful during development, such as function entry/exit points or variable states.
|
||||
|
||||
### Example Usage:
|
||||
|
||||
@@ -74,12 +74,12 @@ router.get('/:id', async (req, res, next) => {
|
||||
|
||||
### Positive
|
||||
|
||||
* **Enhanced Observability**: Every log line from a single request can be instantly grouped and analyzed, dramatically speeding up debugging.
|
||||
* **Improved Security**: Centralizing the addition of context (like `user_id`) reduces the chance of developers manually logging sensitive data.
|
||||
* **Scalable Log Management**: Consistent JSON logs are easily ingested and indexed by any modern log aggregation tool.
|
||||
* **Clearer Code**: Removes the need to manually pass contextual information (like user ID) down to service functions just for logging purposes.
|
||||
**Enhanced Observability**: Every log line from a single request can be instantly grouped and analyzed, dramatically speeding up debugging.
|
||||
**Improved Security**: Centralizing the addition of context (like `user_id`) reduces the chance of developers manually logging sensitive data.
|
||||
**Scalable Log Management**: Consistent JSON logs are easily ingested and indexed by any modern log aggregation tool.
|
||||
**Clearer Code**: Removes the need to manually pass contextual information (like user ID) down to service functions just for logging purposes.
|
||||
|
||||
### Negative
|
||||
|
||||
* **Refactoring Effort**: Requires adding the `requestLogger` middleware and refactoring all routes and services to use `req.log` instead of the global `logger`.
|
||||
* **Slight Performance Overhead**: Creating a child logger for every request adds a minor performance cost, though this is negligible for most modern logging libraries.
|
||||
**Refactoring Effort**: Requires adding the `requestLogger` middleware and refactoring all routes and services to use `req.log` instead of the global `logger`.
|
||||
**Slight Performance Overhead**: Creating a child logger for every request adds a minor performance cost, though this is negligible for most modern logging libraries.
|
||||
@@ -14,5 +14,5 @@ We will adopt a dedicated library for managing server state, such as **TanStack
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Leads to a more performant, predictable, and simpler frontend codebase. Standardizes how the client-side communicates with the server and handles loading/error states. Improves user experience through intelligent caching.
|
||||
* **Negative**: Introduces a new frontend dependency. Requires a learning curve for developers unfamiliar with the library. Requires refactoring of existing data-fetching logic.
|
||||
**Positive**: Leads to a more performant, predictable, and simpler frontend codebase. Standardizes how the client-side communicates with the server and handles loading/error states. Improves user experience through intelligent caching.
|
||||
**Negative**: Introduces a new frontend dependency. Requires a learning curve for developers unfamiliar with the library. Requires refactoring of existing data-fetching logic.
|
||||
@@ -14,5 +14,5 @@ We will implement a dedicated background job processing system using a task queu
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Decouples the API from heavy processing, allows for retries on failure, and enables scaling the processing workers independently. Increases application reliability and resilience.
|
||||
* **Negative**: Introduces a new dependency (Redis) into the infrastructure. Requires refactoring of the flyer processing logic to work within a job queue structure.
|
||||
**Positive**: Decouples the API from heavy processing, allows for retries on failure, and enables scaling the processing workers independently. Increases application reliability and resilience.
|
||||
**Negative**: Introduces a new dependency (Redis) into the infrastructure. Requires refactoring of the flyer processing logic to work within a job queue structure.
|
||||
@@ -14,5 +14,5 @@ We will introduce a centralized, schema-validated configuration service. We will
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Improves application reliability and developer experience by catching configuration errors at startup rather than at runtime. Provides a single source of truth for all required configuration.
|
||||
* **Negative**: Adds a small amount of boilerplate for defining the configuration schema. Requires a one-time effort to refactor all `process.env` access points to use the new configuration service.
|
||||
**Positive**: Improves application reliability and developer experience by catching configuration errors at startup rather than at runtime. Provides a single source of truth for all required configuration.
|
||||
**Negative**: Adds a small amount of boilerplate for defining the configuration schema. Requires a one-time effort to refactor all `process.env` access points to use the new configuration service.
|
||||
@@ -14,5 +14,5 @@ We will adopt a URI-based versioning strategy for the API. All new and existing
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Establishes a critical pattern for long-term maintainability. Allows the API to evolve without breaking existing clients.
|
||||
* **Negative**: Adds a small amount of complexity to the routing setup. Requires discipline to manage versions and deprecations correctly.
|
||||
**Positive**: Establishes a critical pattern for long-term maintainability. Allows the API to evolve without breaking existing clients.
|
||||
**Negative**: Adds a small amount of complexity to the routing setup. Requires discipline to manage versions and deprecations correctly.
|
||||
@@ -17,5 +17,5 @@ We will implement a multi-layered caching strategy using an in-memory data store
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Directly addresses application performance and scalability. Reduces database load and improves API response times for common requests.
|
||||
* **Negative**: Introduces Redis as a dependency if not already used. Adds complexity to the data-fetching logic and requires careful management of cache invalidation to prevent stale data.
|
||||
**Positive**: Directly addresses application performance and scalability. Reduces database load and improves API response times for common requests.
|
||||
**Negative**: Introduces Redis as a dependency if not already used. Adds complexity to the data-fetching logic and requires careful management of cache invalidation to prevent stale data.
|
||||
@@ -17,5 +17,5 @@ We will formalize the testing pyramid for the project, defining the role of each
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Ensures a consistent and comprehensive approach to quality assurance. Gives developers confidence when refactoring or adding new features. Clearly defines "done" for a new feature.
|
||||
* **Negative**: May require investment in setting up and maintaining the E2E testing environment. Can slightly increase the time required to develop a feature if all test layers are required.
|
||||
**Positive**: Ensures a consistent and comprehensive approach to quality assurance. Gives developers confidence when refactoring or adding new features. Clearly defines "done" for a new feature.
|
||||
**Negative**: May require investment in setting up and maintaining the E2E testing environment. Can slightly increase the time required to develop a feature if all test layers are required.
|
||||
@@ -14,5 +14,5 @@ We will implement a real-time communication system using **WebSockets** (e.g., w
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Enables a core, user-facing feature in a scalable and efficient manner. Significantly improves user engagement and experience.
|
||||
* **Negative**: Introduces a new dependency (e.g., WebSocket library) and adds complexity to the backend and frontend architecture. Requires careful handling of connection management and scaling.
|
||||
**Positive**: Enables a core, user-facing feature in a scalable and efficient manner. Significantly improves user engagement and experience.
|
||||
**Negative**: Introduces a new dependency (e.g., WebSocket library) and adds complexity to the backend and frontend architecture. Requires careful handling of connection management and scaling.
|
||||
|
||||
@@ -14,5 +14,5 @@ We will adopt a dedicated database migration tool, such as **`node-pg-migrate`**
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Provides a safe, repeatable, and reversible way to evolve the database schema. Improves team collaboration on database changes. Reduces the risk of data loss or downtime during deployments.
|
||||
* **Negative**: Requires an initial setup and learning curve for the chosen migration tool. All future schema changes must adhere to the migration workflow.
|
||||
**Positive**: Provides a safe, repeatable, and reversible way to evolve the database schema. Improves team collaboration on database changes. Reduces the risk of data loss or downtime during deployments.
|
||||
**Negative**: Requires an initial setup and learning curve for the chosen migration tool. All future schema changes must adhere to the migration workflow.
|
||||
|
||||
@@ -14,5 +14,5 @@ We will implement a feature flagging system. This could start with a simple conf
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Decouples feature releases from code deployments, reducing risk and allowing for more controlled, gradual rollouts and A/B testing. Enables easier experimentation and faster iteration.
|
||||
* **Negative**: Adds complexity to the codebase with conditional logic around features. Requires careful management of feature flag states to avoid technical debt.
|
||||
**Positive**: Decouples feature releases from code deployments, reducing risk and allowing for more controlled, gradual rollouts and A/B testing. Enables easier experimentation and faster iteration.
|
||||
**Negative**: Adds complexity to the codebase with conditional logic around features. Requires careful management of feature flag states to avoid technical debt.
|
||||
|
||||
@@ -14,5 +14,5 @@ We will adopt a framework for internationalization. For the frontend, this will
|
||||
|
||||
## Consequences
|
||||
|
||||
* **Positive**: Lays the architectural groundwork for future global expansion. Improves user experience for non-English speakers.
|
||||
* **Negative**: Requires significant effort to translate all user-facing text. Adds complexity to both frontend and backend code for handling locale-specific data.
|
||||
**Positive**: Lays the architectural groundwork for future global expansion. Improves user experience for non-English speakers.
|
||||
**Negative**: Requires significant effort to translate all user-facing text. Adds complexity to both frontend and backend code for handling locale-specific data.
|
||||
|
||||
@@ -4,16 +4,16 @@ This directory contains a log of the architectural decisions made for the Flyer
|
||||
|
||||
## 1. Foundational / Core Infrastructure
|
||||
|
||||
* **[ADR-002](./0002-standardized-transaction-management.md)**: Standardized Transaction Management and Unit of Work Pattern (Proposed)
|
||||
* **[ADR-007](./0007-configuration-and-secrets-management.md)**: Configuration and Secrets Management (Proposed)
|
||||
* **[ADR-020](./0020-health-checks-and-liveness-readiness-probes.md)**: Health Checks and Liveness/Readiness Probes (Proposed)
|
||||
**[ADR-002](./0002-standardized-transaction-management.md)**: Standardized Transaction Management and Unit of Work Pattern (Proposed)
|
||||
**[ADR-007](./0007-configuration-and-secrets-management.md)**: Configuration and Secrets Management (Proposed)
|
||||
**[ADR-020](./0020-health-checks-and-liveness-readiness-probes.md)**: Health Checks and Liveness/Readiness Probes (Proposed)
|
||||
|
||||
## 2. Data Management
|
||||
|
||||
* **[ADR-009](./0009-caching-strategy-for-read-heavy-operations.md)**: Caching Strategy for Read-Heavy Operations (Proposed)
|
||||
* **[ADR-013](./0013-database-schema-migration-strategy.md)**: Database Schema Migration Strategy (Proposed)
|
||||
* **[ADR-019](./0019-data-backup-and-recovery-strategy.md)**: Data Backup and Recovery Strategy (Proposed)
|
||||
* **[ADR-023](./0023-database-schema-migration-strategy.md)**: Database Schema Migration Strategy (Proposed)
|
||||
**[ADR-009](./0009-caching-strategy-for-read-heavy-operations.md)**: Caching Strategy for Read-Heavy Operations (Proposed)
|
||||
**[ADR-013](./0013-database-schema-migration-strategy.md)**: Database Schema Migration Strategy (Proposed)
|
||||
**[ADR-019](./0019-data-backup-and-recovery-strategy.md)**: Data Backup and Recovery Strategy (Proposed)
|
||||
**[ADR-023](./0023-database-schema-migration-strategy.md)**: Database Schema Migration Strategy (Proposed)
|
||||
|
||||
## 3. API & Integration
|
||||
|
||||
@@ -35,18 +35,18 @@ This directory contains a log of the architectural decisions made for the Flyer
|
||||
|
||||
## 6. Deployment & Operations
|
||||
|
||||
* **[ADR-006](./0006-background-job-processing-and-task-queues.md)**: Background Job Processing and Task Queues (Proposed)
|
||||
* **[ADR-014](./0014-containerization-and-deployment-strategy.md)**: Containerization and Deployment Strategy (Proposed)
|
||||
* **[ADR-017](./0017-ci-cd-and-branching-strategy.md)**: CI/CD and Branching Strategy (Proposed)
|
||||
* **[ADR-024](./0024-feature-flagging-strategy.md)**: Feature Flagging Strategy (Proposed)
|
||||
**[ADR-006](./0006-background-job-processing-and-task-queues.md)**: Background Job Processing and Task Queues (Proposed)
|
||||
**[ADR-014](./0014-containerization-and-deployment-strategy.md)**: Containerization and Deployment Strategy (Proposed)
|
||||
**[ADR-017](./0017-ci-cd-and-branching-strategy.md)**: CI/CD and Branching Strategy (Proposed)
|
||||
**[ADR-024](./0024-feature-flagging-strategy.md)**: Feature Flagging Strategy (Proposed)
|
||||
|
||||
## 7. Frontend / User Interface
|
||||
|
||||
* **[ADR-005](./0005-frontend-state-management-and-server-cache-strategy.md)**: Frontend State Management and Server Cache Strategy (Proposed)
|
||||
* **[ADR-012](./0012-frontend-component-library-and-design-system.md)**: Frontend Component Library and Design System (Proposed)
|
||||
* **[ADR-025](./0025-internationalization-and-localization-strategy.md)**: Internationalization (i18n) and Localization (l10n) Strategy (Proposed)
|
||||
**[ADR-005](./0005-frontend-state-management-and-server-cache-strategy.md)**: Frontend State Management and Server Cache Strategy (Proposed)
|
||||
**[ADR-012](./0012-frontend-component-library-and-design-system.md)**: Frontend Component Library and Design System (Proposed)
|
||||
**[ADR-025](./0025-internationalization-and-localization-strategy.md)**: Internationalization (i18n) and Localization (l10n) Strategy (Proposed)
|
||||
|
||||
## 8. Development Workflow & Quality
|
||||
|
||||
* **[ADR-010](./0010-testing-strategy-and-standards.md)**: Testing Strategy and Standards (Proposed)
|
||||
* **[ADR-021](./0021-code-formatting-and-linting-unification.md)**: Code Formatting and Linting Unification (Proposed)
|
||||
**[ADR-010](./0010-testing-strategy-and-standards.md)**: Testing Strategy and Standards (Proposed)
|
||||
**[ADR-021](./0021-code-formatting-and-linting-unification.md)**: Code Formatting and Linting Unification (Proposed)
|
||||
|
||||
Reference in New Issue
Block a user