Smart Corridor & eGate Hub
The Smart Corridor & eGate Hub is the central system for the biometric corridor and eGate platform. It aggregates events from all internal source systems, normalizes them into a unified event model, and exposes them to external consumers through dedicated service endpoints.
The Hub is the only system end users, integrators, and partners interact with. VPP, CIGS, CBS, and MCT are internal concerns invisible to the outside world.
Repository structure
The Hub is a multi-service repository. Each service is independently deployable but shares a common module for domain models, ORM entities, DTOs, and event notification types.
| Service | Role | Status |
|---|---|---|
| GraphQL API | Live subscriptions and data queries for external consumers | Active |
| DbWorker Service | Event persistence and data retention | Active |
| REST API | Alternative HTTP interface for integrations | Planned |
Shared module — ORM models (IdentificationEvents, Identities, IdentityFaces, ZoneEvents), DTOs, notification types, and RabbitMQ configuration are shared across all services within the repository.
Responsibilities
- Consuming all normalized events from the internal
biometric_eventsmessage broker - Exposing live event subscriptions and historical queries to external consumers
- Persisting finalized outgoing events for short-term audit and retrieval
- Proxying VPP management data (cameras, watchlists, members) for the GUI
- Enforcing configurable data retention and GDPR compliance modes
The VPP Adapter and CIGS Adapter are also Hub components — they live in the Hub repository and are responsible only for translation and routing, containing no business logic.
Data model
The Hub owns the following entities in PostgreSQL:
| Table | Description |
|---|---|
identification_events | Identification outcomes with face crops, full frames, member context |
identities | Anonymous face tracks from CIGS with optional linked identification |
identity_faces | Individual face detections associated with an identity |
zone_events | All zone-level events (entry, exit, count changes, violations, movement) |
VPP entities (cameras, watchlists, members) are not stored locally — they are proxied from VPP on demand by the GraphQL API.
GraphQL API
The GraphQL API is the primary external-facing service of the Hub. It exposes a single /graphql endpoint that serves live event subscriptions over WebSocket or SSE, and historical data queries over HTTP POST. All external consumers — the officer and traveler GUI, partners, and integrators — communicate exclusively through this service; no other Hub service exposes an external interface.
Subscriptions
Live notifications are delivered as GraphQL subscriptions, one per notification topic:
- Identification —
identificationMatch,identificationNoMatch,identificationClearanceGreen,identificationClearanceRed,identificationConditionViolation - Identity Lifecycle —
identityCreated,identityUpdated - Zone —
zonePersonEntered,zonePersonLeft,zonePersonAvoidingIdentification,zoneOccupancyViolation,zonePersonsCountChanged,zonePersonMoved
A combined events(filter: EventFilter) subscription is also available for consumers who prefer a single stream with optional type filtering.
Queries
Historical event queries — events persisted by the DbWorker Service are queryable by event type, time range, unit ID, correlation ID, and source system. Results are paginated and returned in chronological order.
VPP proxy queries — the GraphQL API proxies VPP's management data transparently, presenting it as part of the unified Hub API: cameras, watchlists, and members. These are resolved on demand by delegating to VPP's own GraphQL API; no local copy is stored.
Built with Spring for GraphQL, Kotlin, and Spring Boot 3.x. Internally, a Kotlin Flow bridge routes events consumed from RabbitMQ to the appropriate GraphQL subscription publishers in real time.
DbWorker Service
The DbWorker Service is the persistence and data lifecycle service within the Hub. It writes finalized outgoing events to the database and enforces configurable data retention policies. It has no external interface — it operates entirely as a background service, consuming from RabbitMQ in parallel with and independently of the GraphQL API.
Only finalized outgoing events — the same events exposed externally — are stored, into the tables listed under Data model. Raw or intermediate internal events from VPP, CIGS, CBS, or MCT are never stored. Face crops and full frames are stored directly in PostgreSQL as BYTEA columns; a dedicated object storage service is not required given the short retention window.
Retention
A scheduled job removes expired records from all tables; retention periods are independently configurable per data type. Event records default to 48 hours, image data to 24 hours. Setting STORAGE_ENABLED=false disables persistence entirely — the recommended configuration for GDPR-sensitive deployments where event data must not be stored at rest.
Built with Spring Boot 3.x, Kotlin, Spring Data JPA, and PostgreSQL.
Deployment configuration
Unit configuration is environment-based. A single Hub instance can serve multiple units (corridors and eGates).
STORAGE_ENABLED=true
RETENTION_TTL_EVENTS_HOURS=48
RETENTION_TTL_IMAGES_HOURS=24
RETENTION_JOB_INTERVAL_MINUTES=30
UNITS_0_ID=corridor-a
UNITS_0_NAME=Corridor A
UNITS_0_TYPE=CORRIDOR
UNITS_0_CAMERAS=cam-001,cam-002
UNITS_1_ID=egate-1
UNITS_1_NAME=eGate 1
UNITS_1_TYPE=EGATE
UNITS_1_CAMERAS=cam-010
Future extensions
When eGate-specific notifications diverge from corridor notifications, topic prefixes (corridor.*, egate.*) will be introduced without breaking existing subscribers. The REST API service will expose the same event model over HTTP when available.