- Restore blue PageHeader on Dashboard (/app-components) - Update homepage (/) with subtle header design without blue bar - Add uniform PageHeader styling to application edit page - Fix Rapporten link on homepage to point to /reports overview - Improve header descriptions spacing for better readability
10 KiB
Data Integriteit Plan - Voorkomen van Kapotte Referenties
Probleem
Kapotte referenties ontstaan wanneer attribute_values.reference_object_id verwijst naar objecten die niet in de objects tabel bestaan. Dit kan gebeuren door:
- Objecten verwijderd uit Jira maar referenties blijven bestaan
- Onvolledige sync (niet alle gerelateerde objecten zijn gesynchroniseerd)
- Objecten verwijderd uit cache maar referenties blijven bestaan
- Race conditions tijdens sync
Strategie: Multi-layer Aanpak
Laag 1: Preventie tijdens Sync (Hoogste Prioriteit)
1.1 Referenced Object Validation tijdens Sync
Doel: Zorg dat alle referenced objects bestaan voordat we referenties opslaan
Implementatie:
- Voeg validatie toe in
extractAndStoreRelations()ennormalizeObjectWithDb() - Voor elke reference: check of target object bestaat in cache
- Als target niet bestaat: fetch het object eerst van Jira
- Als object niet in Jira bestaat: sla referentie NIET op (of markeer als "missing")
Code locatie: backend/src/services/normalizedCacheStore.ts
1.2 Deep Sync voor Referenced Objects
Doel: Sync automatisch alle referenced objects tijdens object sync
Implementatie:
- Wanneer een object wordt gesynct, identificeer alle referenced objects
- Queue deze referenced objects voor sync (als ze niet recent gesynct zijn)
- Voer sync uit in dependency order (sync referenced objects eerst)
Code locatie: backend/src/services/syncEngine.ts
1.3 Transactional Reference Storage
Doel: Zorg dat object + referenties atomisch worden opgeslagen
Implementatie:
- Gebruik database transactions voor object + referenties
- Rollback als referenced object niet bestaat
- Valideer alle references voordat commit
Code locatie: backend/src/services/normalizedCacheStore.ts
Laag 2: Database Constraints (Waar Mogelijk)
2.1 Foreign Key Constraints voor Referenties
Doel: Database-level validatie van referenties
Huidige situatie:
attribute_values.reference_object_idheeft GEEN foreign key constraint- Dit is bewust omdat referenced objects mogelijk niet in cache zijn
Optie A: Soft Foreign Key (Aanbevolen)
- Voeg een CHECK constraint toe die valideert dat reference_object_id NULL is OF bestaat in objects
- Dit vereist een database trigger of function
Optie B: Staging Table
- Sla nieuwe referenties eerst op in een staging table
- Valideer en migreer alleen valide referenties naar attribute_values
- Cleanup staging table periodiek
Implementatie: Database migration + trigger/function
2.2 Database Triggers voor Cleanup
Doel: Automatische cleanup wanneer objecten worden verwijderd
Implementatie:
- Trigger op DELETE van objects
- Automatisch verwijder of nullify alle attribute_values met reference_object_id = deleted.id
- Log cleanup acties voor audit
Code locatie: Database migration
Laag 3: Validatie en Cleanup Procedures
3.1 Periodieke Validatie Job
Doel: Detecteer en repareer kapotte referenties automatisch
Implementatie:
- Dagelijkse/nachtelijke job die alle broken references detecteert
- Probeer referenced objects te fetchen van Jira
- Als object bestaat: sync en repareer referentie
- Als object niet bestaat: verwijder referentie (of markeer als "deleted")
Code locatie: backend/src/services/dataIntegrityService.ts (nieuw)
Scheduling: Via cron job of scheduled task
3.2 Manual Cleanup Endpoint
Doel: Admin tool om broken references te repareren
Implementatie:
- POST
/api/data-validation/repair-broken-references - Opties:
mode: 'delete'- Verwijder kapotte referentiesmode: 'fetch'- Probeer objects te fetchen van Jiramode: 'dry-run'- Toon wat er zou gebeuren zonder wijzigingen
Code locatie: backend/src/routes/dataValidation.ts
3.3 Reference Validation tijdens Object Retrieval
Doel: Valideer en repareer referenties wanneer objecten worden opgehaald
Implementatie:
- In
reconstructObject(): check alle references - Als reference broken is: probeer te fetchen van Jira
- Als fetch succesvol: update cache en referentie
- Als fetch faalt: markeer als "missing" in response
Code locatie: backend/src/services/normalizedCacheStore.ts
Laag 4: Sync Verbeteringen
4.1 Dependency-Aware Sync Order
Doel: Sync objecten in de juiste volgorde (dependencies eerst)
Implementatie:
- Analyseer schema om dependency graph te bouwen
- Sync object types in dependency order
- Bijvoorbeeld: sync "Application Function" voordat "Application Component"
Code locatie: backend/src/services/syncEngine.ts
4.2 Batch Sync met Reference Resolution
Doel: Sync batches van objecten en resolve alle references
Implementatie:
- Verzamel alle referenced object IDs tijdens batch sync
- Fetch alle referenced objects in parallel
- Valideer alle references voordat batch commit
Code locatie: backend/src/services/syncEngine.ts
4.3 Incremental Sync met Deletion Detection
Doel: Detecteer verwijderde objecten tijdens incremental sync
Implementatie:
- Vergelijk cache objecten met Jira objecten
- Identificeer objecten die in cache zijn maar niet in Jira
- Verwijder deze objecten (cascade verwijdert referenties)
Code locatie: backend/src/services/syncEngine.ts
Laag 5: Monitoring en Alerting
5.1 Metrics en Dashboard
Doel: Monitor data integriteit in real-time
Implementatie:
- Track broken references count over tijd
- Alert wanneer count boven threshold komt
- Grafiek in dashboard: broken references trend
Code locatie: backend/src/routes/dataValidation.ts + dashboard
5.2 Sync Health Checks
Doel: Valideer data integriteit na elke sync
Implementatie:
- Na sync: check voor broken references
- Log warning als broken references gevonden
- Optioneel: auto-repair tijdens sync
Code locatie: backend/src/services/syncEngine.ts
5.3 Audit Logging
Doel: Track alle data integriteit acties
Implementatie:
- Log wanneer broken references worden gerepareerd
- Log wanneer objecten worden verwijderd
- Log wanneer references worden toegevoegd/verwijderd
Code locatie: Logger service
Implementatie Prioriteiten
Fase 1: Quick Wins (Week 1)
- ✅ Manual cleanup endpoint (
/api/data-validation/repair-broken-references) - ✅ Periodieke validatie job (dagelijks)
- ✅ Metrics in dashboard
Fase 2: Preventie (Week 2-3)
- Referenced object validation tijdens sync
- Deep sync voor referenced objects
- Transactional reference storage
Fase 3: Database Level (Week 4)
- Database triggers voor cleanup
- Soft foreign key constraints (waar mogelijk)
Fase 4: Advanced (Week 5+)
- Dependency-aware sync order
- Incremental sync met deletion detection
- Auto-repair tijdens object retrieval
Technische Details
Referenced Object Validation Pattern
async function validateAndFetchReference(
referenceObjectId: string,
targetType?: string
): Promise<{ exists: boolean; object?: CMDBObject }> {
// 1. Check cache first
const cached = await cacheStore.getObjectById(referenceObjectId);
if (cached) return { exists: true, object: cached };
// 2. Try to fetch from Jira
try {
const jiraObj = await jiraAssetsClient.getObject(referenceObjectId);
if (jiraObj) {
// Parse and cache
const parsed = jiraAssetsClient.parseObject(jiraObj);
if (parsed) {
await cacheStore.upsertObject(parsed._objectType, parsed);
return { exists: true, object: parsed };
}
}
} catch (error) {
if (error instanceof JiraObjectNotFoundError) {
return { exists: false };
}
throw error;
}
return { exists: false };
}
Cleanup Procedure
async function repairBrokenReferences(mode: 'delete' | 'fetch' | 'dry-run'): Promise<{
total: number;
repaired: number;
deleted: number;
failed: number;
}> {
const brokenRefs = await cacheStore.getBrokenReferences(10000, 0);
let repaired = 0;
let deleted = 0;
let failed = 0;
for (const ref of brokenRefs) {
if (mode === 'fetch') {
// Try to fetch from Jira
const result = await validateAndFetchReference(ref.reference_object_id);
if (result.exists) {
repaired++;
} else {
// Object doesn't exist, delete reference
await cacheStore.deleteAttributeValue(ref.object_id, ref.attribute_id);
deleted++;
}
} else if (mode === 'delete') {
await cacheStore.deleteAttributeValue(ref.object_id, ref.attribute_id);
deleted++;
}
// dry-run: just count
}
return { total: brokenRefs.length, repaired, deleted, failed };
}
Success Criteria
- ✅ Broken references count < 1% van totaal aantal referenties
- ✅ Geen nieuwe broken references tijdens normale sync
- ✅ Auto-repair binnen 24 uur na detectie
- ✅ Monitoring dashboard toont real-time integriteit status
- ✅ Sync performance blijft acceptabel (< 10% overhead)
Monitoring
Key Metrics
broken_references_count- Totaal aantal kapotte referentiesbroken_references_rate- Percentage van totaal aantal referentiesreference_repair_success_rate- Percentage succesvol gerepareerde referentiessync_integrity_check_duration- Tijd voor integriteit checkobjects_with_broken_refs- Aantal objecten met kapotte referenties
Alerts
- 🔴 Critical: > 5% broken references
- 🟡 Warning: > 1% broken references
- 🟢 Info: Broken references count veranderd
Rollout Plan
- Week 1: Implementeer cleanup tools en monitoring
- Week 2: Repareer bestaande broken references
- Week 3: Implementeer preventieve maatregelen
- Week 4: Test en monitor
- Week 5: Database-level constraints (optioneel)
Risico's en Mitigatie
| Risico | Impact | Mitigatie |
|---|---|---|
| Sync performance degradation | Hoog | Batch processing, parallel fetching, caching |
| Database locks tijdens cleanup | Medium | Off-peak scheduling, batch size limits |
| False positives in validation | Low | Dry-run mode, manual review |
| Jira API rate limits | Medium | Rate limiting, exponential backoff |
Documentatie Updates
- Update sync engine documentatie
- Update data validation dashboard documentatie
- Create runbook voor broken references cleanup
- Update API documentatie voor nieuwe endpoints