Skip to content

Outreach Service

@nx/outreach captures contact-form inquiries and newsletter subscriptions from the public marketing site. On submission it broadcasts a real-time WebSocket event to admin observation rooms. It is a leaf service with no Kafka and only @nx/core as an internal dependency.

1. Quick Reference

PropertyValue
Package@nx/outreach
CodeSVC-00110-OUTREACH ⚠️ collides with @nx/licensing (SVC-00110); not registered in core ServiceCodes
TypeMicroservice
RuntimeBun
Base ClassVerifierApplication
Locationpackages/outreach
Base Path/v1/api/outreach
Dev Port31110
Container Port3000 (external 31110)
Snowflake ID10
DB Schemaoutreach (2 tables: Inquiry, Subscriber)
Binding Namespace@nx/outreach
Owneroutreach-team

2. Purpose & Scope

IncludedExcluded
Capture contact / sales / demo / partner inquiriesEmail delivery / SMTP (no mail component)
Newsletter subscribe / unsubscribe (idempotent)Kafka event publishing (none)
Subscriber statistics for admin dashboardCRM pipeline automation (manual via CRUD fields)
Real-time WebSocket notification on new inquiryMulti-tenant merchant scoping (global tables)

3. Tech Stack

External:

LibraryPurpose
@venizia/ignisIoC container, DI, BaseService, ControllerFactory, VerifierApplication
@venizia/ignis-helpersWebSocketEmitter, HTTP, env helpers
honoHTTP server framework (via IGNIS)
@hono/zod-openapiRoute schemas → OpenAPI spec
@scalar/hono-api-reference/doc interactive viewer
drizzle-ormDB access via PostgresCoreDataSource
pgPostgreSQL driver

Internal:

PackagePurpose
@nx/coreAll schemas/repositories (Inquiry, Subscriber), VerifierApplication, BaseSocketEventService, Redis factory, migration loader, permission/role/policy repositories

@nx/core is the only internal dependency. No sister-service clients.

4. Project Structure

packages/outreach/
├── src/
│   ├── application.ts          # Application extends VerifierApplication
│   ├── index.ts                # Entry → bootstrapApplication()
│   ├── migrate.ts              # Migration entry → bootstrapMigration()
│   ├── common/                 # RestPaths, constants, keys
│   ├── components/
│   │   └── websocket/          # ApplicationWebSocketComponent + OutreachSocketEventService
│   ├── controllers/
│   │   ├── inquiry/            # InquiryController (+ /submit)
│   │   ├── subscriber/         # SubscriberController (+ subscribe/unsubscribe/statistics)
│   │   └── permissions.ts      # OutreachPermissions (CRUD perms for both entities)
│   ├── datasources/            # PostgresCoreDataSource binding
│   ├── errors/                 # SubscriberErrors, WorkerErrors
│   ├── migrations/processes/   # 0001 seed-permissions, 0002 seed-role-permissions
│   ├── repositories/           # SubscriberRepository (custom getStatistics) + re-exports
│   └── services/               # SubscriberService
├── package.json
└── tsconfig.json

5. Architecture

Detail: see Architecture.

6. Domain Snapshot

No foreign keys between entities — both are independent capture tables. Full ERD + per-entity tables: see Domain Model.

7. Surface Summary

REST controllers (full reference rendered live from /v1/api/outreach/doc/openapi.json):

ControllerBase pathEndpoints
InquiryController/inquiries7 (CRUD + /submit)
SubscriberController/subscribers9 (CRUD + /subscribe, /unsubscribe, /statistics)

Async topics (full reference in API Events):

DirectionCount
Inbound (Kafka)0 (none)
Outbound (Kafka)0 (none)
WebSocket out1 (INQUIRY_SUBMITTED)
BullMQ jobs in0
BullMQ jobs out0

8. Components

ComponentFilePurpose
ApplicationWebSocketComponentsrc/components/websocket/component.tsBuilds Redis-backed WebSocketEmitter (single/cluster), binds it, registers OutreachSocketEventService

9. Services

ServiceFileOne-liner
SubscriberServicesrc/services/subscriber.service.tsIdempotent subscribe, token-based unsubscribe, statistics aggregation
OutreachSocketEventServicesrc/components/websocket/socket-event.service.tsBroadcasts INQUIRY_SUBMITTED to observation rooms (bound by component, not in configureServices)

10. Repositories

RepositoryTableSourceCustom Methods
InquiryRepositoryoutreach.Inquiry@nx/core (re-export)
SubscriberRepositoryoutreach.Subscriberextends core repogetStatistics() — single-query rollup (total / monthlyNew / by-status)

11. Entry Points

FilePurpose
src/index.tsService entry → bootstrapApplication()
src/migrate.tsMigration entry → bootstrapMigration()
src/application.tsApplication class extending VerifierApplication

12. Configuration

Env vars + feature flags + seeded data: see Configuration.

13. Operations

Deployment + observability + security + runbook: see Operations.

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.