Skip to main content

Shared Modules Standard

Version: 1.0
Status: Approved
Owner: Platform Engineering
Last Updated: 2026-04-12
References: system.md §6, AGENT.md §2, §4


1. Purpose

This document defines the purpose, public API boundaries, versioning rules, and forbidden patterns for all packages in the packages/ workspace of the monorepo.


2. Package Inventory

PackagePathPurpose
shared-typespackages/shared-typesTypeScript type definitions shared across services
shared-utilspackages/shared-utilsPure utility functions (HMAC, validation, SMPP PDU helpers)
shared-configpackages/shared-configEnvironment variable schemas and typed config loaders
nats-clientpackages/nats-clientReusable NATS JetStream wrapper with durable consumer helpers
db-clientpackages/db-clientPrisma client wrapper with connection management
loggingpackages/loggingPino logger factory + OpenTelemetry request tracing

3. Package Descriptions and Public APIs

3.1 shared-types

Contains:

  • Message types (SmsMessage, DeliveryReceipt, MessageStatus)
  • Billing types (BillingEvent, Invoice, PricingTier)
  • Operator types (OperatorConfig, SmppBindConfig, RoutingRule)
  • API schemas (Zod schemas for request/response validation, re-exported as types)
  • NATS message envelope types (NatsEnvelope<T>)

Rules:

  • MUST contain only type definitions and Zod schemas.
  • MUST NOT contain business logic.
  • MUST NOT import from any other package except standard TypeScript types.

3.2 shared-utils

Contains:

  • hmacSign(payload: string, secret: string): string — HMAC-SHA256 for webhook signing
  • hmacVerify(payload: string, signature: string, secret: string): boolean
  • validatePhoneNumber(phone: string): boolean — E.164 format validation
  • generateIdempotencyKey(namespace: string, ...parts: string[]): string
  • smppPduHelpers — PDU encoding/decoding utilities

Rules:

  • All functions MUST be pure (no side effects, no I/O).
  • MUST NOT import framework libraries (NestJS, Prisma, NATS).
  • 90%+ unit test coverage required.

3.3 shared-config

Contains:

  • Zod-based environment variable schemas per service
  • loadConfig<T>(schema: ZodSchema): T — validates env vars at startup, throws on missing required vars
  • Common config types (DatabaseConfig, RedisConfig, NatsConfig)

Rules:

  • Services MUST use this package to load config — no direct process.env access in application/domain code.
  • Config MUST be validated at process startup, not lazily.

3.4 nats-client

Contains:

  • createNatsConnection(config: NatsConfig): NatsConnection
  • createJetStreamPublisher(conn, subject): Publisher
  • createDurableConsumer(conn, stream, subject, handler, options): Consumer
  • Retry policy wrappers (exponential backoff with jitter)
  • Dead-letter queue routing helpers

Rules:

  • All consumers MUST be durable — fire-and-forget is forbidden (AGENT.md §9.2).
  • All messages MUST be acknowledged explicitly.
  • DLQ routing MUST be configured for every consumer.

3.5 db-client

Contains:

  • createPrismaClient(config: DatabaseConfig): PrismaClient
  • Connection pooling configuration
  • Transaction helpers
  • Soft-delete utilities

Rules:

  • Services MUST use this wrapper rather than instantiating PrismaClient directly.
  • Connection strings MUST come from shared-config.
  • MUST NOT expose raw SQL escape hatches.

3.6 logging

Contains:

  • createLogger(service: string, config: LogConfig): Logger — Pino logger factory
  • requestTracingMiddleware — injects x-trace-id and x-correlation-id into all requests
  • OpenTelemetry span creation helpers
  • Log level management by environment

Rules:

  • All services MUST use this logger — console.log is forbidden in production (AGENT.md §12.2).
  • Sensitive fields (passwords, API keys, phone numbers in plaintext) MUST be redacted before logging.
  • Trace IDs MUST be propagated to all NATS messages and outbound HTTP calls.

4. Versioning

  • Packages use semantic versioning (MAJOR.MINOR.PATCH).
  • Breaking changes to a package's public API require a MAJOR version bump and a migration guide.
  • All services pin to an exact version in package.json (e.g. "@ghasi/shared-types": "1.2.0").
  • Within the monorepo, pnpm workspace protocol is used: "@ghasi/shared-types": "workspace:*" during development.

5. Consumption Rules

  • Services import from the package's index barrel (@ghasi/shared-types) — never from internal paths.
  • Circular dependencies between packages are forbidden.
  • A service package MUST NOT import from another service package — only from packages/.

6. Forbidden Patterns

PatternReason
Business logic in shared packagesViolates service ownership boundaries
Shared DB models in shared-typesEach service owns its own schema
Direct process.env access in servicesAll config via shared-config
console.logUse logging package
Fire-and-forget NATS publishRequires ack; use nats-client wrappers

7. Assumptions and Open Points

IDAssumption / Open PointOwnerResolution Date
A-001Packages published to private npm registry or consumed via pnpm workspace onlyPlatform EngTBD
A-002shared-config Zod schemas per service to be defined during service scaffoldingEach service teamTBD
A-003OpenTelemetry SDK version to be pinned centrally in root package.jsonPlatform EngTBD