Status: adopted 2026-07-16 (audit R-17,
docs/audits/MONOREPO_ARCHITECTURE_AUDIT_2026-07-16.md). Enforcement is
review-time until lint automation lands.
HTTP server frameworks#
The workspace currently ships four (fastify 114 packages, hono 67, express 19, NestJS 16). For new services:
| Framework | Status | Use for |
|---|---|---|
| fastify | ✅ sanctioned | Platform/backend services (the majority pattern; @lilith/fastify-core exists) |
| hono | ✅ sanctioned | Edge runtimes, BFFs, lightweight gateways |
| express | 🧊 frozen | No new services. Existing 19 packages maintained in place; migrate opportunistically when a service is being rewritten anyway |
| NestJS | 🧊 frozen | No new services. The 16 existing packages are also the only reason emitDecoratorMetadata/experimentalDecorators are on in the global tsconfig (audit R-15) |
HTTP clients#
Use native fetch via @oshun/http-client (timeout, retry,
circuit-breaker, SSRF guard, tracing). axios (6 packages) and node-fetch (3)
are frozen for new code.
Overlapping utility dependencies — resolution policy#
| Overlap | Policy |
|---|---|
uuid vs nanoid vs hand-rolled |
New code uses @oshun/ids (uuid/ulid/prefixedId). uuid/nanoid frozen for new code; migrate via the R-10 rollout |
bcrypt vs bcryptjs |
Do not blind-swap. The 6 bcryptjs users are auth-critical services; hash formats are compatible ($2a/$2b) but native bcrypt adds a compile step to their container builds. Swap per-service with its test suite + image build verified — not mechanically |
crypto-js |
Load-bearing in React Native (apps/lilith/mobile encryption-at-rest; Hermes has no node:crypto, and on-device ciphertext must remain decryptable). Any migration (e.g. to @noble/ciphers) must ship a data-format migration for existing installs. apps/lilith/svc-offline shares formats with mobile. Not a mechanical removal |
@noble/* vs hash.js/crypto-js for NEW code |
New cryptographic code uses node:crypto (services) or @noble/* (cross-platform) |
The audit's R-17 originally framed bcryptjs/crypto-js as simple removals;
investigation during P2 execution (2026-07-16) showed both carry
runtime/deployment constraints, recorded above so nobody "cleans them up"
mechanically.