UI styling improvements: dashboard headers and navigation
- 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
This commit is contained in:
313
docs/DATA-INTEGRITY-PLAN.md
Normal file
313
docs/DATA-INTEGRITY-PLAN.md
Normal file
@@ -0,0 +1,313 @@
|
||||
# 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:
|
||||
1. Objecten verwijderd uit Jira maar referenties blijven bestaan
|
||||
2. Onvolledige sync (niet alle gerelateerde objecten zijn gesynchroniseerd)
|
||||
3. Objecten verwijderd uit cache maar referenties blijven bestaan
|
||||
4. 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()` en `normalizeObjectWithDb()`
|
||||
- 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_id` heeft 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 referenties
|
||||
- `mode: 'fetch'` - Probeer objects te fetchen van Jira
|
||||
- `mode: '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)
|
||||
1. ✅ Manual cleanup endpoint (`/api/data-validation/repair-broken-references`)
|
||||
2. ✅ Periodieke validatie job (dagelijks)
|
||||
3. ✅ Metrics in dashboard
|
||||
|
||||
### Fase 2: Preventie (Week 2-3)
|
||||
4. Referenced object validation tijdens sync
|
||||
5. Deep sync voor referenced objects
|
||||
6. Transactional reference storage
|
||||
|
||||
### Fase 3: Database Level (Week 4)
|
||||
7. Database triggers voor cleanup
|
||||
8. Soft foreign key constraints (waar mogelijk)
|
||||
|
||||
### Fase 4: Advanced (Week 5+)
|
||||
9. Dependency-aware sync order
|
||||
10. Incremental sync met deletion detection
|
||||
11. Auto-repair tijdens object retrieval
|
||||
|
||||
## Technische Details
|
||||
|
||||
### Referenced Object Validation Pattern
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
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 referenties
|
||||
- `broken_references_rate` - Percentage van totaal aantal referenties
|
||||
- `reference_repair_success_rate` - Percentage succesvol gerepareerde referenties
|
||||
- `sync_integrity_check_duration` - Tijd voor integriteit check
|
||||
- `objects_with_broken_refs` - Aantal objecten met kapotte referenties
|
||||
|
||||
### Alerts
|
||||
- 🔴 Critical: > 5% broken references
|
||||
- 🟡 Warning: > 1% broken references
|
||||
- 🟢 Info: Broken references count veranderd
|
||||
|
||||
## Rollout Plan
|
||||
|
||||
1. **Week 1**: Implementeer cleanup tools en monitoring
|
||||
2. **Week 2**: Repareer bestaande broken references
|
||||
3. **Week 3**: Implementeer preventieve maatregelen
|
||||
4. **Week 4**: Test en monitor
|
||||
5. **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
|
||||
Reference in New Issue
Block a user