Skip to content

Module map ​

This map assigns current backend capabilities to their intended module owners. It guides incremental migration; it does not imply that the packages have already moved.

Proposed modules ​

ModuleOwnsNotes
identityAuthentication, users, invitations, global roles, access tokens, refresh sessions, token rotation and revocation behaviourMigrated. Uses Valkey-backed session, rotation, replay-detection, revocation, and security-counter ports.
organizationsOrganizations, organization membership, organization-level imports and organization contextMigrated.
facilitiesFacilities, facility membership, departments, locations and facility contextMigrated.
governanceGovernance profiles, capabilities, approval policies, policy documents and governance authorizationMigrated. Exposes GovernanceCapabilityAuthorizer from its root package; re-exported capability constants live in shared/governance to break import cycles.
devicesDevice catalog, manufacturers, brands, models, device records, images, imports, utilization and device lifecycleMigrated.
lifecycleAsset lifecycle events: recalls, incidents, transfers, refurbishments, retirement reviews and disposalsMigrated.
maintenanceFault reports, work orders, preventive-maintenance schedules and maintenance operationsMigrated.
procurementNeed requests, option appraisals, acquisition records, commercial records and donationsMigrated.
counterpartiesCounterparty records and vendor contractsMigrated.
billingPlans, subscriptions, billing transactions, payment provider integration and payment webhook retentionMigrated. Payment provider adapter lives in adapters/payment.
notificationsNotification records, notification preferences or delivery requests, and coordination of email deliveryMigrated.
auditAudit event recording, audit queries and retention policyMigrated.
referenceStable reference and lookup data used across modulesMigrated from legacy lookup domain.

Devices terminology and scope ​

devices is the canonical module name. It owns two related but distinct concepts:

  • Device: a catalog definition, such as a manufacturer/model/type of medical equipment.
  • DeviceRecord: a physical device managed by an organization or facility.

The module also owns device lifecycle operations such as utilization, retirement, transfer, recall, and refurbishment.

Acquisition is a workflow owned by procurement. When acquisition results in a physical device being registered, Procurement calls the public Devices API to create a DeviceRecord. Procurement must not insert directly into Devices-owned tables.

Reference-data ownership ​

The reference module should only own genuinely shared, stable vocabularies. Lookup data that represents a specific module's business rules belongs to that module even if it is exposed through a lookup-style endpoint.

Assigned module-owned reference data includes:

  • work-order statuses, priorities, and types: maintenance;
  • failure codes: maintenance;
  • device types, categories, functions, and application risks: devices;
  • electrical safety classes, applied-part types, power sources, backup-power sources, and regulatory classes: devices;
  • location categories: facilities;
  • organization types: organizations;
  • subscription plans: billing;
  • user roles: identity;
  • generic statuses: temporary reference ownership until status families are separated by business meaning.

Existing /api/v1/lookup routes may remain stable while ownership moves behind them.

Infrastructure layers ​

The following are not business modules. They form four distinct layers:

platform/ — infrastructure ports and generic utilities ​

Provider-neutral interfaces and cross-cutting utilities. Modules depend on these interfaces, never on concrete implementations.

PackageResponsibility
platform/configTyped process configuration (API, worker, scheduler)
platform/databasePool lifecycle, migrations and tenant-schema mechanics
platform/cacheProvider-neutral cache interface (Get/Set/Delete)
platform/sessionRefresh-session store: activate, rotate, revoke
platform/idempotencyDistributed in-flight reservation (Acquired/InProgress/Conflict)
platform/ratelimitDistributed rate-limiter port (Allow → Decision)
platform/leaseDistributed lease coordination for background workers
platform/securitycounterDistributed abuse counters (failed logins, lockout state)
platform/distributedstateFacade aggregating all Valkey-backed capabilities
platform/messagingDurable job queue (transactional outbox + Valkey signal)
platform/loggerContext-aware slog wrapper with request/user/facility correlation
platform/metricsPrometheus HTTP, DB pool, and auth instrumentation
platform/retryExponential backoff retry with context support
platform/circuitbreakerCircuit-breaker pattern for external service calls
platform/observabilityLogging, metrics and tracing integration points

adapters/ — concrete provider implementations ​

Implement platform interfaces using specific vendors. Constructed in app and injected into modules as narrow interface types.

PackageResponsibility
adapters/mailResend (production) and NoOp email implementations
adapters/storageCloudflare R2 and NoOp object-storage implementations
adapters/paymentPaystack (production) and NoOp payment-provider implementations
adapters/fxExchange-rate fetcher with circuit breaker, retry, and cache

common/ — Ovahol-specific shared application code ​

Packages that encode Ovahol business policy or application conventions. Not generic infrastructure; not a dumping ground.

PackageResponsibility
common/errorsAppError type and predefined HTTP-mapped error taxonomy
common/rolesRBAC role constants and ValidRoles lookup map
common/plansSubscription plan code constants and family normalization
common/featuresFeature-flag resolver tied to plan entitlements and roles
common/configAuth config loader (JWT secrets, lockout thresholds, seed admin)
common/responseAPIResponse JSON envelope for all HTTP responses
common/utilsGeneral helpers: fingerprinting, password validation, slice ops
common/paginationLimit/Offset DTO with normalization defaults

shared/ — cycle-breaking value types ​

A type belongs here only when it is stable, has no clear module owner, and would otherwise create an import cycle. Keep this package intentionally small.

PackageResponsibility
shared/governanceGovernanceActorScope and capability constants used across lifecycle, procurement, and governance without creating cycles

Boundary questions to resolve during extraction ​

The following decisions should be made from actual transactional and change patterns while modules are extracted:

  • whether governance later needs policy roles distinct from Identity-owned authentication and membership roles;
  • whether device dictionary recommendations remain within devices or become a separately owned integration capability;
  • whether notification persistence and delivery remain one module or delivery becomes a worker adapter;
  • whether organization imports belong to organizations while device imports remain in devices;
  • whether audit retention is owned by audit or implemented as an application-level operational job.

These open questions do not block the initial module structure. Until decided, new code should follow the owner named in the table above.

Ovahol developer documentation