docs(adr): convert all ADRs to MADR 2.1.2 format
Rewrites all 7 backend ADRs from a custom structure to the MADR 2.1.2 template required by the VS Code ADR Manager extension: bullet metadata (Status/Date), standardised section headings, "Chosen option: X, because Y" wording, and explicit Pros/Cons blocks per option.
This commit is contained in:
@@ -1,24 +1,49 @@
|
|||||||
# ADR 0001: Backend Framework — Express.js
|
# Use Express.js as the HTTP framework
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The backend serves a JSON REST API consumed by the Angular frontend. The requirements are straightforward: HTTP routing, middleware chaining, JSON body parsing, JWT authentication, and database access. No server-side rendering, no real-time features, no heavy framework conventions are needed.
|
The backend serves a JSON REST API consumed by the Angular frontend. Requirements are straightforward: HTTP routing, middleware chaining, JSON body parsing, JWT authentication, and database access. No server-side rendering, real-time features, or heavy framework conventions are needed. Which HTTP framework should be used?
|
||||||
|
|
||||||
## Decision
|
## Considered Options
|
||||||
|
|
||||||
Use Express.js as the HTTP framework. The application is structured around:
|
* Express.js
|
||||||
- `src/routes/api/<domain>/` — route definitions by functional domain
|
* Fastify
|
||||||
- `src/controllers/` — request/response handling
|
* NestJS
|
||||||
- `src/services/` — business logic
|
|
||||||
- `src/middlewares/` — cross-cutting concerns (auth, error handling, async wrapper)
|
|
||||||
- `createApp.js` — application factory (separates app creation from server startup, enabling testability)
|
|
||||||
|
|
||||||
## Consequences
|
## Decision Outcome
|
||||||
|
|
||||||
- **Positive:** Minimal abstraction. Full control over middleware order and request lifecycle.
|
Chosen option: "Express.js", because it provides full control over middleware order and request lifecycle with minimal abstraction, and is well understood without requiring conventions to be learned.
|
||||||
- **Positive:** Large ecosystem. Well-understood by the team.
|
|
||||||
- **Negative:** No convention over configuration — project structure is manually maintained.
|
The application is structured around: `src/routes/api/<domain>/` (route definitions), `src/controllers/` (request/response handling), `src/services/` (business logic), `src/middlewares/` (cross-cutting concerns), and `createApp.js` (application factory separating app creation from server startup for testability).
|
||||||
- **Negative:** Async error handling requires explicit wrapping (`asyncHandler` middleware) since Express 4 does not catch promise rejections natively. Express 5 (not yet used) handles this automatically.
|
|
||||||
|
### Positive Consequences
|
||||||
|
|
||||||
|
* Minimal abstraction — full control over middleware order and request lifecycle.
|
||||||
|
* Large ecosystem with well-understood patterns.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* No convention over configuration — project structure is manually maintained.
|
||||||
|
* Async error handling requires explicit wrapping (`asyncHandler` middleware) since Express 4 does not catch promise rejections natively. Express 5 (not yet used) handles this automatically.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### Express.js
|
||||||
|
|
||||||
|
* Good, because minimal and flexible — no forced conventions.
|
||||||
|
* Good, because widely known ecosystem.
|
||||||
|
* Bad, because no built-in async error handling in v4.
|
||||||
|
|
||||||
|
### Fastify
|
||||||
|
|
||||||
|
* Good, because faster than Express, built-in schema validation.
|
||||||
|
* Bad, because less familiar; migration cost not justified for current scale.
|
||||||
|
|
||||||
|
### NestJS
|
||||||
|
|
||||||
|
* Good, because strong conventions, TypeScript-first, built-in dependency injection.
|
||||||
|
* Bad, because heavyweight — conventions and abstractions are not needed for a straightforward REST API.
|
||||||
|
* Bad, because would require migrating the entire codebase.
|
||||||
|
|||||||
@@ -1,27 +1,47 @@
|
|||||||
# ADR 0002: Database Migration — MongoDB to MySQL with Sequelize
|
# Migrate from MongoDB to MySQL with Sequelize
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The project initially used MongoDB (evidence: `mongo:start`/`mongo:stop` Docker scripts still present in `package.json`, and `$oid` ObjectId references in the original data export). MongoDB was likely chosen for its flexible schema during early prototyping.
|
The project initially used MongoDB, likely chosen for its flexible schema during early prototyping (evidence: `mongo:start`/`mongo:stop` Docker scripts in `package.json`, `$oid` ObjectId references in original data exports). As the data model stabilised and relational queries became more common (joins between users, jumps, canopies, drop zones), a relational database became a better fit. Should the database be migrated?
|
||||||
|
|
||||||
As the data model stabilised and relational queries became more common (joins between users, jumps, canopies, drop zones, etc.), a relational database became a better fit. MySQL is a well-known, widely hosted relational database with strong Sequelize support.
|
## Considered Options
|
||||||
|
|
||||||
## Decision
|
* Migrate to MySQL with Sequelize
|
||||||
|
* Keep MongoDB
|
||||||
|
|
||||||
Migrate to MySQL with Sequelize as the ORM. Sequelize provides:
|
## Decision Outcome
|
||||||
- Model definitions with typed fields
|
|
||||||
- Migration system (`sequelize-cli db:migrate`) for schema versioning
|
|
||||||
- Seeders for initial reference data
|
|
||||||
- Relationship declarations (`src/database/relationships/`)
|
|
||||||
|
|
||||||
The `mongo:start`/`mongo:stop` npm scripts are legacy artefacts and can be removed when confirmed no longer needed.
|
Chosen option: "Migrate to MySQL with Sequelize", because the data model is now stable and relational, and MySQL with Sequelize provides migrations, seeders, and relationship declarations that MongoDB cannot enforce at the database level.
|
||||||
|
|
||||||
## Consequences
|
Sequelize provides: model definitions with typed fields, a migration system (`sequelize-cli db:migrate`) for schema versioning, seeders for initial reference data, and relationship declarations (`src/database/relationships/`). The original MongoDB data was exported and re-imported into MySQL via a one-shot migration script (since removed).
|
||||||
|
|
||||||
- **Positive:** Relational integrity enforced at the database level. Joins are first-class.
|
### Positive Consequences
|
||||||
- **Positive:** Sequelize migrations provide a reproducible setup path (`npm run setup:api`).
|
|
||||||
- **Negative:** Less flexible schema than MongoDB — changes require migrations.
|
* Relational integrity enforced at the database level. Joins are first-class.
|
||||||
- **Note:** The original data was exported from MongoDB (documents with `$oid` fields) and re-imported into MySQL via a one-shot migration script. That script has since been removed from the frontend codebase.
|
* Sequelize migrations provide a reproducible setup path (`npm run setup:api`).
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* Less flexible schema than MongoDB — changes require migrations.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### MySQL with Sequelize
|
||||||
|
|
||||||
|
* Good, because enforces relational integrity at the database level.
|
||||||
|
* Good, because migrations provide a versioned, reproducible schema.
|
||||||
|
* Bad, because schema changes require explicit migration files.
|
||||||
|
|
||||||
|
### Keep MongoDB
|
||||||
|
|
||||||
|
* Good, because flexible schema — no migrations needed for model changes.
|
||||||
|
* Bad, because relational queries (joins) are complex and not first-class.
|
||||||
|
* Bad, because referential integrity is not enforced at the database level.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* The one-shot MongoDB → MySQL import script was removed from the frontend codebase (see `importJumps()` removal in `logbook.component.ts`).
|
||||||
|
* The `mongo:start`/`mongo:stop` npm scripts in `package.json` are legacy artefacts from the MongoDB era and can be removed.
|
||||||
|
|||||||
@@ -1,23 +1,50 @@
|
|||||||
# ADR 0003: REST API with Swagger Documentation
|
# Document the REST API with OpenAPI/Swagger
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The API must be understandable and testable without reading source code. Two documentation approaches were considered:
|
The API must be understandable and testable without reading source code. How should the API be documented?
|
||||||
- **OpenAPI/Swagger** — industry standard, generates interactive UI, supports code generation.
|
|
||||||
- **Postman collection** — already present (`tests/adastra-api-tests.postman_collection.json`), good for integration testing but not a substitute for living documentation.
|
|
||||||
|
|
||||||
## Decision
|
## Considered Options
|
||||||
|
|
||||||
Use `swagger-jsdoc` + `swagger-ui-express` to generate and serve an interactive OpenAPI 3.0 documentation at a dedicated route. Annotations are written as JSDoc comments directly in route/controller files.
|
* OpenAPI/Swagger (`swagger-jsdoc` + `swagger-ui-express`)
|
||||||
|
* Postman collection only
|
||||||
|
* No documentation
|
||||||
|
|
||||||
Postman collections are kept for integration/regression testing (run via `npm run test:postman` with Newman), complementing rather than replacing Swagger.
|
## Decision Outcome
|
||||||
|
|
||||||
## Consequences
|
Chosen option: "OpenAPI/Swagger", because it generates living, interactive documentation directly from the source code, eliminating the risk of documentation drift.
|
||||||
|
|
||||||
- **Positive:** Living documentation — always in sync with the code.
|
`swagger-jsdoc` + `swagger-ui-express` generate and serve an interactive OpenAPI 3.0 UI at a dedicated route. Annotations are written as JSDoc comments directly in route/controller files. The existing Postman collection (`tests/adastra-api-tests.postman_collection.json`) is kept for integration and regression testing via Newman (`npm run test:postman`), complementing rather than replacing Swagger.
|
||||||
- **Positive:** Interactive UI allows manual endpoint testing without a separate tool.
|
|
||||||
- **Positive:** OpenAPI spec can be used to generate client types if needed.
|
### Positive Consequences
|
||||||
- **Negative:** JSDoc annotations add verbosity to route files. Annotations must be kept up to date manually.
|
|
||||||
|
* Living documentation — always in sync with the code.
|
||||||
|
* Interactive UI allows manual endpoint testing without a separate tool.
|
||||||
|
* OpenAPI spec can be used to generate client types if needed.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* JSDoc annotations add verbosity to route files.
|
||||||
|
* Annotations must be kept up to date manually — stale annotations are possible if discipline slips.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### OpenAPI/Swagger
|
||||||
|
|
||||||
|
* Good, because interactive UI — testable in the browser without Postman.
|
||||||
|
* Good, because spec is co-located with the code it describes.
|
||||||
|
* Bad, because requires discipline to keep annotations accurate.
|
||||||
|
|
||||||
|
### Postman collection only
|
||||||
|
|
||||||
|
* Good, because already present; useful for regression testing.
|
||||||
|
* Bad, because not suitable as primary documentation — requires Postman to view.
|
||||||
|
* Bad, because collection and code can diverge silently.
|
||||||
|
|
||||||
|
### No documentation
|
||||||
|
|
||||||
|
* Good, because zero maintenance overhead.
|
||||||
|
* Bad, because API is opaque without reading the source.
|
||||||
|
|||||||
@@ -1,22 +1,46 @@
|
|||||||
# ADR 0004: Route Organisation by Functional Domain
|
# Organise routes by functional domain
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The API covers four independent functional domains (skydive, cms, ecommerce, herowars), each with distinct models, business logic, and frontend consumers. A flat route structure would make it difficult to reason about domain boundaries and onboard new contributors.
|
The API covers four independent functional domains (skydive, cms, ecommerce, herowars), each with distinct models, business logic, and frontend consumers. How should routes be organised to reflect these boundaries?
|
||||||
|
|
||||||
## Decision
|
## Considered Options
|
||||||
|
|
||||||
Routes are grouped under `src/routes/api/<domain>/` with a barrel index (`src/routes/api/index.js`). Each domain owns its routes, controllers, services, and models independently. The domain prefix is reflected in the API path (e.g. `/api/skydive/jumps`, `/api/cms/articles`).
|
* Domain-based organisation (`src/routes/api/<domain>/`)
|
||||||
|
* Flat structure (all routes at one level)
|
||||||
|
|
||||||
This structure mirrors the frontend's domain organisation (see frontend ADR 0011), making the full-stack data flow traceable: a frontend service under `core/services/skydive/` calls `/skydive/` routes, which map to `src/routes/api/skydive/`.
|
## Decision Outcome
|
||||||
|
|
||||||
Legacy `v1/`, `v2/`, `v3/` directories exist alongside the active routes as backup snapshots from earlier iterations. They are slated for removal once their contents are confirmed no longer needed (see ADR 0007).
|
Chosen option: "Domain-based organisation", because it makes domain boundaries explicit and mirrors the frontend's service structure, making the full-stack data flow traceable.
|
||||||
|
|
||||||
## Consequences
|
Routes are grouped under `src/routes/api/<domain>/` with a barrel index (`src/routes/api/index.js`). The domain prefix is reflected in the API path (e.g. `/api/skydive/jumps`, `/api/cms/articles`). Each domain owns its routes, controllers, services, and models independently. This structure mirrors the frontend's domain organisation (see frontend ADR 0011).
|
||||||
|
|
||||||
- **Positive:** Domain boundaries are explicit and enforced by directory structure.
|
### Positive Consequences
|
||||||
- **Positive:** Consistent mapping between frontend service paths and backend routes simplifies debugging.
|
|
||||||
- **Negative:** Cross-domain features (shared auth middleware, user model) live in `src/middlewares/` and `src/database/models/` respectively, outside any domain folder.
|
* Domain boundaries are explicit and enforced by directory structure.
|
||||||
|
* Consistent mapping between frontend service paths and backend routes simplifies debugging — a frontend service under `core/services/skydive/` maps to `src/routes/api/skydive/`.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* Cross-domain features (shared auth middleware, user model) live in `src/middlewares/` and `src/database/models/` respectively, outside any domain folder.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### Domain-based organisation
|
||||||
|
|
||||||
|
* Good, because each domain is self-contained and independently navigable.
|
||||||
|
* Good, because symmetric with the frontend service structure.
|
||||||
|
* Bad, because shared concerns need a neutral layer outside domain folders.
|
||||||
|
|
||||||
|
### Flat structure
|
||||||
|
|
||||||
|
* Good, because simpler for very small APIs.
|
||||||
|
* Bad, because domain boundaries become invisible as the API grows.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* Legacy `v1/`, `v2/`, `v3/` directories exist alongside `api/` as backup snapshots from earlier iterations — see [ADR 0007](0007-legacy-routes-removal.md) for their planned removal.
|
||||||
|
* Related to frontend [ADR 0011](../../adastra_app/docs/decisions/0011-feature-domain-organisation.md)
|
||||||
|
|||||||
@@ -1,24 +1,46 @@
|
|||||||
# ADR 0005: Frontend and Backend in Separate Repositories
|
# Maintain frontend and backend in separate repositories
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The frontend (Angular SPA) and backend (Express API) are distinct deployment units with different runtimes, dependencies, and release cycles. Two organisational options exist:
|
The frontend (Angular SPA) and backend (Express API) are distinct deployment units with different runtimes, dependencies, and release cycles. Should they live in the same repository or in separate ones?
|
||||||
|
|
||||||
- **Monorepo** — single repository containing both applications, possibly managed with Nx or Turborepo.
|
## Considered Options
|
||||||
- **Separate repositories** — each application in its own repository with independent versioning.
|
|
||||||
|
|
||||||
## Decision
|
* Separate repositories (`adastra_app` and `adastra_api`)
|
||||||
|
* Monorepo (managed with Nx or Turborepo)
|
||||||
|
|
||||||
Maintain two separate repositories: `adastra_app` (frontend) and `adastra_api` (backend). Both are treated as a single product during development — tasks that span both (e.g. adding a new API endpoint and its frontend consumer) are handled in a single working session across both repos.
|
## Decision Outcome
|
||||||
|
|
||||||
## Consequences
|
Chosen option: "Separate repositories", because the two applications have independent dependency trees and deployment lifecycles, and the current scale does not justify the tooling overhead of a monorepo.
|
||||||
|
|
||||||
- **Positive:** Independent dependency management. Frontend and backend `package.json` files don't interfere with each other.
|
Both repositories are treated as a single product during development: the Angular frontend's `CLAUDE.md` declares `adastra_api` as an additional working directory so that cross-repo tasks can be handled in a single session. Tasks that span both (e.g. adding an endpoint and its frontend consumer) are handled together.
|
||||||
- **Positive:** Simpler CI/CD pipeline per repo when production deployment is set up.
|
|
||||||
- **Positive:** Each repo's git history reflects only its own changes.
|
### Positive Consequences
|
||||||
- **Negative:** No shared type definitions between frontend and backend. API contract changes must be coordinated manually.
|
|
||||||
- **Negative:** Cross-repo changes require two separate commits/PRs. A monorepo would allow atomic cross-boundary commits.
|
* Independent dependency management — `package.json` files don't interfere with each other.
|
||||||
- **Tooling note:** The Angular frontend's `CLAUDE.md` declares `adastra_api` as an additional working directory so that cross-repo tasks can be handled in a single session.
|
* Simpler per-repo CI/CD pipeline when production deployment is configured.
|
||||||
|
* Each repo's git history reflects only its own changes.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* No shared type definitions between frontend and backend. API contract changes must be coordinated manually.
|
||||||
|
* Cross-repo changes require two separate commits. A monorepo would allow atomic cross-boundary commits.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### Separate repositories
|
||||||
|
|
||||||
|
* Good, because independent dependency management and deployment.
|
||||||
|
* Good, because clean git history per application.
|
||||||
|
* Bad, because no shared types — API contract drift must be caught manually.
|
||||||
|
* Bad, because cross-repo changes require coordinated commits in two places.
|
||||||
|
|
||||||
|
### Monorepo (Nx or Turborepo)
|
||||||
|
|
||||||
|
* Good, because atomic cross-boundary commits and shared type definitions.
|
||||||
|
* Good, because single place to run all tasks (build, test, lint).
|
||||||
|
* Bad, because significant tooling overhead not justified at the current scale.
|
||||||
|
* Bad, because requires migrating both repos and learning monorepo tooling.
|
||||||
|
|||||||
@@ -1,28 +1,53 @@
|
|||||||
# ADR 0006: Authentication — JWT with express-jwt
|
# Use JWT for API authentication
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: accepted
|
||||||
**Status:** Accepted
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The API must authenticate requests from the Angular frontend. Options considered:
|
The API must authenticate requests from the Angular frontend. How should user identity be verified on each request?
|
||||||
- **Session-based auth** — server stores session state; requires sticky sessions or shared session store in multi-instance deployments.
|
|
||||||
- **JWT (JSON Web Tokens)** — stateless; token carries the user identity; no server-side session storage.
|
|
||||||
|
|
||||||
Given that the application is currently single-instance with no horizontal scaling requirement, either would work. JWT is simpler to operate and aligns with the frontend's existing token-based auth flow.
|
## Decision Drivers
|
||||||
|
|
||||||
## Decision
|
* Application is currently single-instance with no horizontal scaling requirement.
|
||||||
|
* Frontend already uses token-based auth (stores JWT in `localStorage` — see frontend ADR 0005).
|
||||||
|
* Simplicity of operation is preferred over session infrastructure.
|
||||||
|
|
||||||
Use JWT for authentication:
|
## Considered Options
|
||||||
- Tokens are issued by the API on successful login (`jsonwebtoken` library, `bcrypt` for password hashing).
|
|
||||||
- Incoming requests are validated by the `express-jwt` middleware, which populates `req.auth` with the decoded token payload.
|
|
||||||
- The `src/middlewares/auth.js` middleware wraps `express-jwt` and handles role-based access control (`Admin` role required for protected admin routes).
|
|
||||||
|
|
||||||
The frontend stores the token in `localStorage` and sends it as `Authorization: Token <jwt>` (see frontend ADR 0005).
|
* JWT (JSON Web Tokens) with `express-jwt`
|
||||||
|
* Session-based authentication
|
||||||
|
|
||||||
## Consequences
|
## Decision Outcome
|
||||||
|
|
||||||
- **Positive:** Stateless — no session store needed. Horizontally scalable without sticky sessions.
|
Chosen option: "JWT", because it is stateless (no session store needed), aligns with the frontend's existing token-based auth flow, and is simpler to operate for a single-instance deployment.
|
||||||
- **Positive:** Single middleware handles auth for all routes.
|
|
||||||
- **Negative:** Tokens cannot be invalidated server-side before expiry. Acceptable for this use case (internal application, low revocation risk).
|
Tokens are issued on successful login (`jsonwebtoken` library, `bcrypt` for password hashing). Incoming requests are validated by `express-jwt`, which populates `req.auth` with the decoded payload. The `src/middlewares/auth.js` middleware wraps `express-jwt` and handles role-based access control (`Admin` role required for protected admin routes). The frontend sends tokens as `Authorization: Token <jwt>`.
|
||||||
- **Security:** Passwords are hashed with `bcrypt`. The JWT secret must be kept in environment configuration, never committed.
|
|
||||||
|
### Positive Consequences
|
||||||
|
|
||||||
|
* Stateless — no session store needed. Horizontally scalable without sticky sessions.
|
||||||
|
* Single middleware handles auth for all routes.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* Tokens cannot be invalidated server-side before expiry. Acceptable for this use case (internal application, low revocation risk).
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### JWT
|
||||||
|
|
||||||
|
* Good, because stateless — no session store infrastructure.
|
||||||
|
* Good, because works seamlessly with the frontend's `localStorage`-based token flow.
|
||||||
|
* Bad, because revocation requires token blacklisting, which adds state.
|
||||||
|
|
||||||
|
### Session-based authentication
|
||||||
|
|
||||||
|
* Good, because sessions can be invalidated immediately server-side.
|
||||||
|
* Bad, because requires a session store (Redis or database-backed) — adds infrastructure complexity.
|
||||||
|
* Bad, because sticky sessions or a shared store are needed in multi-instance deployments.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* Related to frontend [ADR 0005](../../adastra_app/docs/decisions/0005-jwt-authentication-localstorage.md)
|
||||||
|
* Security note: passwords are hashed with `bcrypt`. The JWT secret must be kept in environment configuration, never committed.
|
||||||
|
|||||||
@@ -1,25 +1,52 @@
|
|||||||
# ADR 0007: Removal of Legacy Route Directories (v1, v2, v3)
|
# Remove legacy route directories v1, v2, v3
|
||||||
|
|
||||||
**Date:** 2026-04-26
|
* Status: proposed
|
||||||
**Status:** Proposed
|
* Date: 2026-04-26
|
||||||
|
|
||||||
## Context
|
## Context and Problem Statement
|
||||||
|
|
||||||
The `src/routes/` directory contains three legacy subdirectories (`v1/`, `v2/`, `v3/`) alongside the active `api/` directory. These are backup snapshots of earlier API iterations, kept during the migration to the current domain-based structure. They are not mounted in the application and serve no runtime purpose.
|
The `src/routes/` directory contains three legacy subdirectories (`v1/`, `v2/`, `v3/`) alongside the active `api/` directory. These are backup snapshots of earlier API iterations kept during the migration to the current domain-based structure. They are not mounted in the application. Should they be removed?
|
||||||
|
|
||||||
Their presence:
|
## Decision Drivers
|
||||||
- Creates confusion about which routes are active.
|
|
||||||
- Adds noise to `grep` and IDE navigation.
|
|
||||||
- Risks accidentally referencing stale logic.
|
|
||||||
|
|
||||||
## Decision
|
* Legacy directories create confusion about which routes are active.
|
||||||
|
* They add noise to `grep` output and IDE navigation.
|
||||||
|
* Stale logic risks being accidentally referenced.
|
||||||
|
|
||||||
Remove `v1/`, `v2/`, and `v3/` directories once the following is confirmed:
|
## Considered Options
|
||||||
- No active code references them (direct imports or dynamic requires).
|
|
||||||
- Their content has been superseded by the equivalent routes under `src/routes/api/`.
|
|
||||||
|
|
||||||
## Consequences
|
* Remove `v1/`, `v2/`, `v3/` after verification
|
||||||
|
* Keep them indefinitely
|
||||||
|
|
||||||
- **Positive:** Cleaner repository. Only active routes remain.
|
## Decision Outcome
|
||||||
- **Risk:** If any code path still references these directories, removal would cause a runtime error. Verify with `grep -r "routes/v[123]"` before deleting.
|
|
||||||
- **Status rationale:** Marked as *Proposed* rather than *Accepted* until the verification step is completed and the deletion is committed.
|
Chosen option: "Remove after verification", because the directories serve no runtime purpose and their presence actively harms codebase clarity.
|
||||||
|
|
||||||
|
Before deletion, verify: no active code references them (direct imports or dynamic requires) and their content has been superseded by the equivalent routes under `src/routes/api/`. Verification command: `grep -r "routes/v[123]" src/`.
|
||||||
|
|
||||||
|
This ADR is marked *proposed* rather than *accepted* until the verification step is completed and the deletion is committed.
|
||||||
|
|
||||||
|
### Positive Consequences
|
||||||
|
|
||||||
|
* Cleaner repository — only active routes remain visible.
|
||||||
|
* Eliminates the risk of accidentally referencing stale logic.
|
||||||
|
|
||||||
|
### Negative Consequences
|
||||||
|
|
||||||
|
* If any code path still references these directories, removal would cause a runtime error. The verification step mitigates this risk.
|
||||||
|
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### Remove after verification
|
||||||
|
|
||||||
|
* Good, because removes dead code that harms navigability.
|
||||||
|
* Bad, because irreversible without git history — must verify before deleting.
|
||||||
|
|
||||||
|
### Keep indefinitely
|
||||||
|
|
||||||
|
* Good, because no risk of breakage.
|
||||||
|
* Bad, because perpetuates confusion about what is active.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* Related to [ADR 0004](0004-route-organisation-by-domain.md) — domain-based `api/` structure that replaces these legacy directories.
|
||||||
|
|||||||
Reference in New Issue
Block a user