HOCO B2B
Team tasksAnis

SRV-04 — Server foundation — Express + oRPC, errors, logging, rate limits, API reference

HTTP app skeleton: oRPC OpenAPI handler under /v1, error envelope, request ids, pino logging, CORS, rate limiting, Idempotency-Key middleware, /health, /openapi.json and the Scalar reference.

FieldDetails
Task codeSRV-04
PhaseP0 — Foundations (cadrage, UX/UI, architecture & contract)
Product scopeV1
StatusDone (Sun 18 Oct 2026)
StartSun 18 Oct 2026
DueSun 18 Oct 2026
ResponsibleAnis — Full-stack developer
Co-responsible—
Effort0.5 person-day(s) planned · 3 from scratch · size XS
Area · appServer · server
Depends onSRV-03
UnblocksSRV-05, SRV-07, OPS-02
Milestones—

Summary

HTTP app skeleton: oRPC OpenAPI handler under /v1, error envelope, request ids, pino logging, CORS, rate limiting, Idempotency-Key middleware, /health, /openapi.json and the Scalar reference.

Description

Every module needs the same HTTP foundation, so this task builds it once (NFR-01, NFR-08, SYN-05): an Express app that mounts the oRPC OpenAPI handler under /v1, maps every error to the envelope { error: { code, message, details, requestId } } with messages localised by Accept-Language (fr default, ar, en), assigns request ids, logs with pino (secrets redacted), applies CORS for the dashboard and web origins with credentials, rate-limits through Redis, and enforces the Idempotency-Key contract with IdempotencyRecord (replay with Idempotent-Replayed: true, 409 IDEMPOTENCY_KEY_REUSED on a different body, 30-day retention). It also adds the app-version gate (426 UPGRADE_REQUIRED from AppVersionPolicy), /health and /ready, /openapi.json and the Scalar reference at /reference, and the worker process entry point. Out of scope: authentication (SRV-05) and permissions (SRV-06). All module tasks plug their procedures into this skeleton.

Subtasks

#SubtaskOwner
1Express app with oRPC OpenAPIHandler under /v1, context builder (requestId, locale, client app, device id, user)Anis
2Error mapping: ORPCError and Zod issues → envelope; 422 VALIDATION_FAILED with field paths; unknown errors → 500 INTERNAL_ERROR without leaking stack tracesAnis
3Message catalogue fr/ar/en for every registered error code, selected by Accept-LanguageAnis
4pino logger with request logging, redaction of password, otp, token and Authorization, and Sentry error captureAnis
5CORS for app.hoco.dz and the dashboard origin with credentials; security headersAnis
6Redis rate limiter (sliding window) with route-specific limits and 429 RATE_LIMITED + Retry-AfterAnis
7Idempotency middleware: body hash, in-progress lock, replay with Idempotent-Replayed, 409 IDEMPOTENCY_KEY_REUSED, 400 IDEMPOTENCY_KEY_REQUIRED on mandatory routes, 30-day purge jobAnis
8App-version gate reading AppVersionPolicy (min version per app/platform) → 426 UPGRADE_REQUIRED, maintenance mode → 503 MAINTENANCEAnis
9/health, /ready (Postgres + Redis), /openapi.json and Scalar /reference; graceful shutdown of api and workerAnis

Deliverables

  • apps/server/src/{app,context,errors,i18n}.ts and apps/server/src/middleware/{request-id,logger,cors,rate-limit,idempotency,app-version}.ts
  • apps/server/src/entry/{api,worker}.ts
  • apps/server/src/i18n/errors.{fr,ar,en}.json

Acceptance criteria

  • Every error response, including validation and unknown errors, follows the envelope and carries the same requestId as the X-Request-Id header
  • Replaying a mutating call with the same Idempotency-Key and body returns the original response with Idempotent-Replayed: true; a different body returns 409 IDEMPOTENCY_KEY_REUSED
  • A mobile request below the minimum version returns 426 UPGRADE_REQUIRED
  • Exceeding 600 requests per minute for one user returns 429 with Retry-After
  • /reference renders the OpenAPI document generated from packages/contracts
  • Logs never contain passwords, OTP codes or bearer tokens

Requirements covered

RequirementTitleRelease
NFR-01Performance: app opens and search/filter results in under 3 s on a normal mobile connection; API p95 targetsV1
NFR-08Logging of sensitive actions and technical errors; monitoring and alertingV1
SYN-05Sync queue handling retries, duplicates (idempotency), errors and conflictsV1

Test measures

  • Unit tests for the error mapper and locale selection
  • Integration tests against real Redis and Postgres for idempotency (concurrent same key, replay, reuse with different body)
  • Rate-limit test with a burst script

Risks

  • Idempotency race when two identical requests arrive together — insert the record with a unique key and an in-progress state before executing; the second waits or gets 409 IDEMPOTENCY_IN_PROGRESS

KPI

  • Delivered by Sun 18 Oct 2026 within 0.5 person-day(s).
  • Every acceptance criterion above demonstrated before hand-off; linked requirements' acceptance criteria pass.
  • Zero open critical defects, permission gaps or data-integrity regressions at sign-off.

Generated from content/plan/tasks.json by scripts/generate-team-tasks.mjs. Dates are computed by the scheduler (Sunday–Thursday weeks, holidays excluded) — change the plan, not this page.

On this page