Labels / Complexity: enhancement · High — 800
Context
The service logs per request but never correlates them. src/app.ts mounts morgan('dev') for access logs, src/config/logger.ts emits Winston logs with a simple() format, and src/middleware/error.middleware.ts logs errors and returns an envelope — but none of these attach a shared request identifier. When a request fans out across a controller, the rewards/Stellar service, and the error handler, there is no way to group its log lines.
The roadmap already commits to this work:
// docs/ROADMAP.md — "Next"
- Add structured request IDs and propagate them across logs and HTTP responses.
A naive hardcoded console.log of a counter would not survive a multi-replica deployment and would not be retrievable by the client, which is the whole point of a request ID.
Goal
Assign every incoming request a unique, propagated identifier, include it in all log lines produced while handling that request, and return it to the client in every response (and in the error envelope) so an operator can trace a single request end to end from the access log through service logs to the HTTP response.
Scope
1. Request ID assignment middleware
Add middleware early in src/app.ts (before morgan and routes) that reads an inbound X-Request-Id (validating it, and rejecting or sanitizing values over a bounded length) or generates one, then stores it on the request. Decide the format (UUID v4 vs. a short nonce) and whether a client-supplied value is trusted or always overwritten.
2. Log correlation
Propagate the request ID into the Winston logger and morgan so every line includes it. Extend src/config/logger.ts (currently format.simple()) with the request ID as structured metadata, and configure morgan in src/app.ts to emit the token. Decide whether the logger reads the ID from an async-local storage context or from an explicit argument passed down the call chain.
3. Response and error propagation
Return the ID on every response — a X-Request-Id header and/or a requestId field — and add it to the errorHandler envelope in src/middleware/error.middleware.ts (both the success-adjacent and error shapes). Ensure asyncHandler and notFoundHandler also preserve it.
4. Tests and documentation
Cover the middleware (generates a valid ID, honors/overwrites an inbound one, rejects an oversized value) and the error handler (ID present on error responses). Document the header in docs/API.md and docs/OPERATIONS.md.
Downstream impact
Adding a response header and an error-envelope field is backward-compatible for clients that ignore unknown fields. Kqirox/Orivex-Frontend is unaffected (it makes no live requests yet). No bindings are regenerated.
Acceptance criteria
Middleware
Logging
Error responses
Tests
Documentation
Out of scope
Do not implement OpenTelemetry tracing in this issue (that is a separate roadmap item); request IDs are plain correlation, not spans.
Getting started
Files in scope: src/app.ts, src/config/logger.ts, src/middleware/error.middleware.ts, src/utils/logger.ts, docs/API.md, docs/OPERATIONS.md.
Commands: pnpm lint, pnpm build, pnpm test:ci.
Good first files to read: src/app.ts, src/config/logger.ts, src/middleware/error.middleware.ts.
Labels / Complexity: enhancement · High — 800
Context
The service logs per request but never correlates them.
src/app.tsmountsmorgan('dev')for access logs,src/config/logger.tsemits Winston logs with asimple()format, andsrc/middleware/error.middleware.tslogs errors and returns an envelope — but none of these attach a shared request identifier. When a request fans out across a controller, the rewards/Stellar service, and the error handler, there is no way to group its log lines.The roadmap already commits to this work:
A naive hardcoded
console.logof a counter would not survive a multi-replica deployment and would not be retrievable by the client, which is the whole point of a request ID.Goal
Assign every incoming request a unique, propagated identifier, include it in all log lines produced while handling that request, and return it to the client in every response (and in the error envelope) so an operator can trace a single request end to end from the access log through service logs to the HTTP response.
Scope
1. Request ID assignment middleware
Add middleware early in
src/app.ts(beforemorganand routes) that reads an inboundX-Request-Id(validating it, and rejecting or sanitizing values over a bounded length) or generates one, then stores it on the request. Decide the format (UUID v4 vs. a short nonce) and whether a client-supplied value is trusted or always overwritten.2. Log correlation
Propagate the request ID into the Winston logger and
morganso every line includes it. Extendsrc/config/logger.ts(currentlyformat.simple()) with the request ID as structured metadata, and configuremorganinsrc/app.tsto emit the token. Decide whether the logger reads the ID from an async-local storage context or from an explicit argument passed down the call chain.3. Response and error propagation
Return the ID on every response — a
X-Request-Idheader and/or arequestIdfield — and add it to theerrorHandlerenvelope insrc/middleware/error.middleware.ts(both the success-adjacent and error shapes). EnsureasyncHandlerandnotFoundHandleralso preserve it.4. Tests and documentation
Cover the middleware (generates a valid ID, honors/overwrites an inbound one, rejects an oversized value) and the error handler (ID present on error responses). Document the header in
docs/API.mdanddocs/OPERATIONS.md.Downstream impact
Adding a response header and an error-envelope field is backward-compatible for clients that ignore unknown fields.
Kqirox/Orivex-Frontendis unaffected (it makes no live requests yet). No bindings are regenerated.Acceptance criteria
Middleware
X-Request-Id(or equivalent) whose value is a valid, bounded identifier.X-Request-Idis either honored (after validation) or safely overwritten, per the documented decision, and oversized or malformed values never crash the handler.Logging
morgan, Winston, anderror.middleware.tsinclude the same request ID for a single request.Error responses
errorHandlerenvelope includes the request ID alongsideerror.messageanderror.code.Tests
Documentation
docs/API.mdanddocs/OPERATIONS.mddocument theX-Request-Idheader and how to query logs by it.Out of scope
Do not implement OpenTelemetry tracing in this issue (that is a separate roadmap item); request IDs are plain correlation, not spans.
Getting started
Files in scope:
src/app.ts,src/config/logger.ts,src/middleware/error.middleware.ts,src/utils/logger.ts,docs/API.md,docs/OPERATIONS.md.Commands:
pnpm lint,pnpm build,pnpm test:ci.Good first files to read:
src/app.ts,src/config/logger.ts,src/middleware/error.middleware.ts.