Nothing persisted agent heartbeats before: companion_last_seen was written once at setup and connection_status stayed 'connected' forever. HostAgentConsumerService now consumes corrosion.*.host.heartbeat (updates last_seen + status, auto-creates the bare_metal connection row on first contact), host.going_offline (graceful offline), and sweeps connections offline after 180s of heartbeat silence. License-existence tenant validation with caching per NATS-consumer doctrine. WS bridge forwards host_heartbeat/host_going_offline to the panel. Contract-verified against production NATS with the backend's own nats lib: v2 subjects, schema 2, real telemetry, offline beacon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
152 lines
5.3 KiB
TypeScript
152 lines
5.3 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
import { JwtModule } from '@nestjs/jwt';
|
|
import { APP_GUARD } from '@nestjs/core';
|
|
import { ScheduleModule } from '@nestjs/schedule';
|
|
import configuration from './config/configuration';
|
|
|
|
// Guards
|
|
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
|
|
import { PermissionsGuard } from './common/guards/permissions.guard';
|
|
import { LicenseGuard } from './common/guards/license.guard';
|
|
|
|
// Feature Modules
|
|
import { AuthModule } from './modules/auth/auth.module';
|
|
import { UsersModule } from './modules/users/users.module';
|
|
import { LicensesModule } from './modules/licenses/licenses.module';
|
|
import { ServersModule } from './modules/servers/servers.module';
|
|
import { PlayersModule } from './modules/players/players.module';
|
|
import { WipesModule } from './modules/wipes/wipes.module';
|
|
import { MapsModule } from './modules/maps/maps.module';
|
|
import { PluginsModule } from './modules/plugins/plugins.module';
|
|
import { ChatModule } from './modules/chat/chat.module';
|
|
import { TeamModule } from './modules/team/team.module';
|
|
import { NotificationsModule } from './modules/notifications/notifications.module';
|
|
import { SettingsModule } from './modules/settings/settings.module';
|
|
import { SchedulesModule } from './modules/schedules/schedules.module';
|
|
import { AnalyticsModule } from './modules/analytics/analytics.module';
|
|
import { AlertsModule } from './modules/alerts/alerts.module';
|
|
import { StatusModule } from './modules/status/status.module';
|
|
import { StoreModule } from './modules/store/store.module';
|
|
import { WebstoreModule } from './modules/webstore/webstore.module';
|
|
import { AdminModule } from './modules/admin/admin.module';
|
|
import { SetupModule } from './modules/setup/setup.module';
|
|
import { MigrationModule } from './modules/migration/migration.module';
|
|
import { ChangelogModule } from './modules/changelog/changelog.module';
|
|
import { FilesModule } from './modules/files/files.module';
|
|
import { LootModule } from './modules/loot/loot.module';
|
|
import { TeleportModule } from './modules/teleport/teleport.module';
|
|
import { GatherModule } from './modules/gather/gather.module';
|
|
import { AutoDoorsModule } from './modules/autodoors/autodoors.module';
|
|
import { KitsModule } from './modules/kits/kits.module';
|
|
import { FurnaceSplitterModule } from './modules/furnacesplitter/furnacesplitter.module';
|
|
import { BetterChatModule } from './modules/betterchat/betterchat.module';
|
|
import { TimedExecuteModule } from './modules/timedexecute/timedexecute.module';
|
|
import { RaidableBasesModule } from './modules/raidablebases/raidablebases.module';
|
|
import { EarlyAccessModule } from './modules/early-access/early-access.module';
|
|
|
|
// Shared Services
|
|
import { NatsService } from './services/nats.service';
|
|
import { NatsBridgeService } from './services/nats-bridge.service';
|
|
import { HostAgentConsumerService } from './services/host-agent-consumer.service';
|
|
import { ServerConnection } from './entities/server-connection.entity';
|
|
import { License } from './entities/license.entity';
|
|
import { SteamService } from './services/steam.service';
|
|
|
|
// Gateway
|
|
import { NatsBridgeGateway } from './gateways/nats-bridge.gateway';
|
|
|
|
@Module({
|
|
imports: [
|
|
// Configuration
|
|
ConfigModule.forRoot({
|
|
isGlobal: true,
|
|
load: [configuration],
|
|
}),
|
|
|
|
// Database
|
|
TypeOrmModule.forRootAsync({
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => ({
|
|
type: 'postgres' as const,
|
|
url: config.get<string>('database.url'),
|
|
autoLoadEntities: true,
|
|
synchronize: false, // NEVER auto-sync — use migrations only
|
|
extra: {
|
|
max: config.get<number>('database.maxConnections') || 20,
|
|
},
|
|
}),
|
|
}),
|
|
|
|
// JWT (global)
|
|
JwtModule.registerAsync({
|
|
global: true,
|
|
inject: [ConfigService],
|
|
useFactory: (config: ConfigService) => ({
|
|
secret: config.get<string>('jwt.secret'),
|
|
signOptions: {
|
|
expiresIn: `${config.get<number>('jwt.accessExpirySeconds') || 900}s`,
|
|
},
|
|
}),
|
|
}),
|
|
|
|
// Scheduler
|
|
ScheduleModule.forRoot(),
|
|
|
|
// Repositories for app-level shared services (host-agent consumer)
|
|
TypeOrmModule.forFeature([ServerConnection, License]),
|
|
|
|
// Feature Modules
|
|
AuthModule,
|
|
UsersModule,
|
|
LicensesModule,
|
|
ServersModule,
|
|
PlayersModule,
|
|
WipesModule,
|
|
MapsModule,
|
|
PluginsModule,
|
|
ChatModule,
|
|
TeamModule,
|
|
NotificationsModule,
|
|
SettingsModule,
|
|
SchedulesModule,
|
|
AnalyticsModule,
|
|
AlertsModule,
|
|
StatusModule,
|
|
StoreModule,
|
|
WebstoreModule,
|
|
AdminModule,
|
|
SetupModule,
|
|
MigrationModule,
|
|
ChangelogModule,
|
|
FilesModule,
|
|
LootModule,
|
|
TeleportModule,
|
|
GatherModule,
|
|
AutoDoorsModule,
|
|
KitsModule,
|
|
FurnaceSplitterModule,
|
|
BetterChatModule,
|
|
TimedExecuteModule,
|
|
RaidableBasesModule,
|
|
EarlyAccessModule,
|
|
],
|
|
providers: [
|
|
// Global guards (order matters: auth first, then license, then permissions)
|
|
{ provide: APP_GUARD, useClass: JwtAuthGuard },
|
|
{ provide: APP_GUARD, useClass: PermissionsGuard },
|
|
|
|
// Shared services
|
|
NatsService,
|
|
NatsBridgeService,
|
|
HostAgentConsumerService,
|
|
SteamService,
|
|
|
|
// WebSocket gateway
|
|
NatsBridgeGateway,
|
|
],
|
|
exports: [NatsService, NatsBridgeService, SteamService],
|
|
})
|
|
export class AppModule {}
|