Skip to main content

AI Brief: hbf-data-manager

NestJS service that persists per-interaction metadata produced by hbf-bot during workflow execution. Writes come in via Kafka; reads are served over a JWT-guarded REST API.

What This Repo Does

hbf-data-manager consumes interaction-metadata events from Kafka (published by hbf-bot) and stores them in MySQL as InteractionMetadata rows. It exposes a read API for org users (guarded by hbf-core token validation) to list, filter, and inspect those records, and a write-delete API (guarded by a local DM-issued JWT) used by hbf-data-retention to clean up sessions.

Tech Stack

  • Language: TypeScript
  • Framework: NestJS 11 (Express platform)
  • Key dependencies: TypeORM 0.3 (MySQL), kafkajs 2.2, @helvia/hbf-core-api 30, @nestjs/jwt, nestjs-pino

Entry Points

  • Main: src/main.ts
  • App module: src/app.module.ts
  • ORM config: ormconfig.ts (migration CLI only)

Key Directories

DirectoryPurpose
src/interactions/InteractionMetadata entity, read controller, delete controller, service, DTOs
src/queue/Kafka consumer: subscribes to topics and calls InteractionsService.saveMetadata
src/auth/Two guards: HBFGuard (delegates to hbf-core), DMJwtGuard (local HS256 JWT)
src/clients/CoreClientService: HTTP client wrapping hbf-core /users/me
src/migrations/TypeORM migration files for interaction_metadata table
src/utils/Shared DTOs (User, UserRole) and sleep helper
src/health/Health check controller on GET / and GET /health

API Endpoints

MethodPathGuardDescription
GET/orgs/:orgId/interactionsHBFGuardList all interaction metadata (desc by ts)
GET/orgs/:orgId/events/:hbfEventId/interactionsHBFGuardGet records for a specific HBF event (sortable)
GET/orgs/:orgId/events/:hbfEventId/session-variablesHBFGuardLatest VARIABLE-type records as of event timestamp
DELETE/chat-sessions/:sessionId/interactionsDMJwtGuardAsync delete all records for a session (202)
POST/chat-sessions/interactions/bulk-deleteDMJwtGuardAsync bulk delete by session IDs (202)
GET/healthnoneService health check

Data Model

Table: interaction_metadata

ColumnTypeNotes
idBIGINT PKAuto-increment
hbf_event_idCHAR(36)HBF event UUID
session_idCHAR(36)ChatSession UUID
tsTIMESTAMPInteraction timestamp
typeTEXTE.g., "VARIABLE", "NODE", etc.
friendly_nameTEXT nullableHuman-readable node label
payloadJSONEvent-specific data
has_errorBOOLEAN nullableWhether the interaction errored
duration_msINT nullableDuration in milliseconds
created_atTIMESTAMPRow creation time
updated_atTIMESTAMPRow last updated time

Indexes: idx_session_ts (session_id, ts), idx_hbf_event_ts (hbf_event_id, ts)

External Dependencies

  • MySQL 8: Primary data store (hbf_data_manager database)
  • Kafka: Consumes interaction-metadata topic (configurable via KAFKA_TOPICS). Supports local PLAINTEXT and Confluent Cloud SASL_SSL.
  • hbf-core: Token validation via GET /users/me (env: CORE_URL)

Auth

Two guard patterns:

  1. HBFGuard (read endpoints): Calls hbf-core GET /users/me with the incoming Bearer token. Allows moderators unconditionally; allows org-role holders for the requested orgId.
  2. DMJwtGuard (delete endpoints): Verifies a locally-issued HS256 JWT signed with DM_AUTH_JWT_SECRET. Used by internal services (e.g., hbf-data-retention) to delete session data.

Key Environment Variables

VariableDefaultPurpose
MYSQL_HOSTlocalhostMySQL host
MYSQL_PORT3306MySQL port
MYSQL_USERrootMySQL username
MYSQL_PASSWORDrootMySQL password
MYSQL_DBhbf_data_managerMySQL database name
CORE_URLhttp://localhost:8080hbf-core base URL
KAFKA_BROKERSlocalhost:9092Comma-separated Kafka brokers
KAFKA_TOPICSinteraction-metadataComma-separated topics to consume
KAFKA_GROUP_IDhbf-data-manager-consumerConsumer group ID
KAFKA_SECURITY_PROTOCOLPLAINTEXTPLAINTEXT or SASL_SSL
KAFKA_SASL_USERNAMEConfluent Cloud username
KAFKA_SASL_PASSWORDConfluent Cloud password
DM_AUTH_JWT_SECRETSecret for DMJwtGuard (delete API)
TYPEORM_AUTORUN_MIGRATIONSfalseAuto-run migrations on startup
DB_SYNCHRONIZEfalseTypeORM schema sync (keep false in prod)
PORT3000HTTP listen port
PINO_LOGGER_USEfalseEnable Pino structured logging
PINO_LOG_LEVELinfoPino log level

Running Locally

# Start MySQL only
docker compose up -d db

# Run with hot reload
MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USER=hbf MYSQL_PASSWORD=hbf MYSQL_DB=hbf_data_manager npm run start:dev

API: http://localhost:3000 Swagger: http://localhost:3000/api (non-production only)

Migrations

npm run migration:run    # apply pending migrations
npm run migration:revert # revert last migration

Tests

npm test          # unit tests
npm run test:e2e # e2e tests
npm run test:cov # coverage