feat(US-1105..1108): Server-side settings sync for telemetry, attachments, agents

- Add syncSettingsToServices() to propagate feature settings to services
- Telemetry service reads enabled/retention/traces from feature settings
- Attachment service reads dynamic limits from task behavior settings
- Sync on startup from config file and on every PATCH /api/settings/features
- Add setLimits() to AttachmentService for runtime limit updates
This commit is contained in:
Brad Groux 2026-01-28 02:35:07 -06:00
parent 4681aad9d7
commit fd30fac03f
5 changed files with 90 additions and 5 deletions

View file

@ -388,3 +388,5 @@
{"type":"task.status_changed","taskId":"task_20260128_itHuxN","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_NOCEuvNIHTiv","timestamp":"2026-01-28T08:20:05.575Z"}
{"type":"task.status_changed","taskId":"task_20260128_Kbjd3t","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_pboz3ar-apIo","timestamp":"2026-01-28T08:20:05.585Z"}
{"type":"task.status_changed","taskId":"task_20260128_iG-ISb","project":"platform","status":"done","previousStatus":"in-progress","id":"evt_9NMBR9OcmaQV","timestamp":"2026-01-28T08:24:03.292Z"}
{"type":"task.status_changed","taskId":"task_20260128_DUyAbh","project":"veritas-kanban","status":"done","previousStatus":"in-progress","id":"evt_UfgftrtLSNBu","timestamp":"2026-01-28T08:32:47.510Z"}
{"type":"task.status_changed","taskId":"task_20260128_vYzfwx","project":"veritas-kanban","status":"done","previousStatus":"in-progress","id":"evt_SttjD2RNNe2h","timestamp":"2026-01-28T08:32:47.536Z"}

View file

@ -1,4 +1,48 @@
[
{
"id": "activity_1769589172887_jp4y9jj7c",
"type": "comment_added",
"taskId": "task_20260128_vYzfwx",
"taskTitle": "US-1104: Task behavior settings",
"details": {
"author": "Veritas",
"preview": "Task behavior settings wired in TaskDetailPanel: d..."
},
"timestamp": "2026-01-28T08:32:52.887Z"
},
{
"id": "activity_1769589172877_npxiqczo8",
"type": "comment_added",
"taskId": "task_20260128_DUyAbh",
"taskTitle": "US-1103: Board & display settings",
"details": {
"author": "Veritas",
"preview": "Board & display settings complete: sprint badges o..."
},
"timestamp": "2026-01-28T08:32:52.877Z"
},
{
"id": "activity_1769589167537_tukrzq1ly",
"type": "status_changed",
"taskId": "task_20260128_vYzfwx",
"taskTitle": "US-1104: Task behavior settings",
"details": {
"from": "in-progress",
"status": "done"
},
"timestamp": "2026-01-28T08:32:47.537Z"
},
{
"id": "activity_1769589167510_sgfq2w68c",
"type": "status_changed",
"taskId": "task_20260128_DUyAbh",
"taskTitle": "US-1103: Board & display settings",
"details": {
"from": "in-progress",
"status": "done"
},
"timestamp": "2026-01-28T08:32:47.510Z"
},
{
"id": "activity_1769588643293_d36yhzq9l",
"type": "status_changed",

View file

@ -21,8 +21,9 @@ import telemetryRoutes from './routes/telemetry.js';
import metricsRoutes from './routes/metrics.js';
import tracesRoutes from './routes/traces.js';
import attachmentRoutes from './routes/attachments.js';
import { settingsRoutes } from './routes/settings.js';
import { settingsRoutes, syncSettingsToServices } from './routes/settings.js';
import { getTelemetryService } from './services/telemetry-service.js';
import { ConfigService } from './services/config-service.js';
import { initBroadcast } from './services/broadcast-service.js';
import type { AgentOutput } from './services/agent-service.js';
@ -60,10 +61,17 @@ app.use('/api/metrics', metricsRoutes);
app.use('/api/traces', tracesRoutes);
app.use('/api/settings', settingsRoutes);
// Initialize telemetry service (runs retention cleanup)
getTelemetryService().init().catch((err) => {
console.error('Failed to initialize telemetry service:', err);
});
// Initialize telemetry service and sync with feature settings
(async () => {
try {
const configService = new ConfigService();
const featureSettings = await configService.getFeatureSettings();
syncSettingsToServices(featureSettings);
await getTelemetryService().init();
} catch (err) {
console.error('Failed to initialize telemetry service:', err);
}
})();
// Create HTTP server
const server = createServer(app);

View file

@ -1,9 +1,34 @@
import { Router, type Router as RouterType } from 'express';
import { ConfigService } from '../services/config-service.js';
import { getTelemetryService } from '../services/telemetry-service.js';
import { getAttachmentService } from '../services/attachment-service.js';
import type { FeatureSettings } from '@veritas-kanban/shared';
const router: RouterType = Router();
const configService = new ConfigService();
/**
* Sync feature settings to affected server-side services.
* Called on PATCH and on server startup.
*/
export function syncSettingsToServices(settings: FeatureSettings): void {
// Sync telemetry settings
const telemetry = getTelemetryService();
telemetry.configure({
enabled: settings.telemetry.enabled,
retention: settings.telemetry.retentionDays,
traces: settings.telemetry.enableTraces,
});
// Sync attachment limits
const attachments = getAttachmentService();
attachments.setLimits({
maxFileSize: settings.tasks.attachmentMaxFileSize,
maxFilesPerTask: settings.tasks.attachmentMaxPerTask,
maxTotalSize: settings.tasks.attachmentMaxTotalSize,
});
}
// GET /api/settings/features — returns full feature settings with defaults merged
router.get('/features', async (_req, res) => {
try {
@ -23,6 +48,8 @@ router.patch('/features', async (req, res) => {
return res.status(400).json({ error: 'Body must be a JSON object with feature settings' });
}
const updated = await configService.updateFeatureSettings(patch);
// Sync settings to server-side services
syncSettingsToServices(updated);
res.json(updated);
} catch (error) {
console.error('Error updating feature settings:', error);

View file

@ -61,6 +61,10 @@ export class AttachmentService {
/**
* Get attachment limits configuration
*/
setLimits(limits: AttachmentLimits): void {
this.limits = limits;
}
getLimits(): AttachmentLimits {
return this.limits;
}