ADR-016: Configuration-Driven Entity UI
Status
Implemented
Date
2025-01-16 (Retrospective)
Decision Makers
- Frontend Team - UI architecture
- Architecture Team - Pattern standardization
Layer
Frontend
Related ADRs
- ADR-006: React 18 with Material-UI v7
- ADR-015: Plugin System Architecture
- ADR-003: Three-Tier Entity Hierarchy
Supersedes
None
Depends On
- ADR-006: React 18 with Material-UI v7
Context
Managing 17 entity types requires consistent UI patterns:
- Code Duplication: Each entity page had similar but different code
- Inconsistency: Features varied between entity types
- Maintenance: Fixing bugs required changes in 17+ places
- Onboarding: New entities required significant development
- Feature Parity: Hard to ensure all entities had same capabilities
Requirements:
- Single source of truth for entity behavior
- Quick onboarding of new entities
- Consistent UX across all entities
- Type-safe configuration
- Easy customization where needed
Decision
We implement configuration-driven entity UI with unified components:
Key Design Decisions
- Entity Configuration: JSON-like TypeScript config per entity
- Unified Components: EntityListPage, EntityDetailPage shared
- Feature Flags: Per-entity feature enablement
- Column Definitions: Declarative table columns
- Form Schemas: Declarative form fields
Entity Configuration Structure
interface EntityConfig {
name: string;
plural: string;
apiPath: string;
icon: React.ComponentType;
// Features
features: {
search: boolean;
bulkDelete: boolean;
export: boolean;
import: boolean;
comments: boolean;
history: boolean;
relationships: boolean;
};
// Table
columns: ColumnDef[];
defaultSort: { field: string; order: 'asc' | 'desc' };
// Forms
createFields: FormField[];
editFields: FormField[];
// Actions
rowActions: RowAction[];
bulkActions: BulkAction[];
// Customization
detailTabs?: TabConfig[];
metrics?: MetricConfig;
}
Usage Pattern
// config/entityConfigs.ts
export const requirementConfig: EntityConfig = {
name: 'Requirement',
plural: 'Requirements',
apiPath: '/api/v1/requirements',
icon: DescriptionIcon,
features: {
search: true,
bulkDelete: true,
export: true,
import: true,
comments: true,
history: true,
relationships: true,
},
columns: [...],
// ...
};
// pages/Requirements.tsx
export const Requirements = () => (
<EntityListPage config={requirementConfig} />
);
Unified Components
| Component | Purpose |
|---|---|
| EntityListPage | Standard list view with table |
| EntityDetailPage | Detail view with tabs |
| EntityEditDialog | Create/edit modal |
| EntityDeleteDialog | Delete confirmation |
| EntityFilters | Filter sidebar |
| EntitySearch | Search with suggestions |
Consequences
Positive
- 90% Code Reduction: Single implementation for all entities
- Instant Parity: New features apply to all entities
- Type Safety: TypeScript validates all configurations
- Easy Onboarding: New entity = new config file
- Consistent UX: Users learn once, use everywhere
- Maintainability: Fix once, fix everywhere
Negative
- Configuration Complexity: Large config objects
- Limited Flexibility: Edge cases need escape hatches
- Learning Curve: Must understand config schema
- Type Definitions: Complex TypeScript types
Neutral
- Bundle Size: Single component vs many specific ones
- Performance: Slightly more props to process
Alternatives Considered
1. Copy-Paste Components
- Approach: Duplicate components per entity
- Rejected: Maintenance nightmare, inconsistency
2. Higher-Order Components
- Approach: HOC pattern for shared behavior
- Rejected: Harder to type, wrapper hell
3. Inheritance
- Approach: Class inheritance for pages
- Rejected: Not idiomatic React, less flexible
Implementation Status
- Core implementation complete
- Tests written and passing
- Documentation updated
- Migration/upgrade path defined
- Monitoring/observability in place
Implementation Details
- Configs:
frontend/src/config/entityConfigs.ts - List Page:
frontend/src/components/entities/EntityListPage.tsx - Detail Page:
frontend/src/components/entities/EntityDetailPage.tsx - Types:
frontend/src/types/entityConfig.ts - Docs:
docs/development/entity-development-guide.md
Compliance/Validation
- Automated checks: TypeScript validates configs
- Manual review: New configs reviewed for consistency
- Metrics: None (development pattern)
LLM Council Review
Review Date: 2025-01-16 Confidence Level: High (100%) Verdict: STRONG APPROVAL
Quality Metrics
- Consensus Strength Score (CSS): 0.95
- Deliberation Depth Index (DDI): 0.88
Council Feedback Summary
Unanimous consensus that configuration-driven UI is the correct pattern for managing 17 entity types. The 90% code reduction is realistic because SRE operations prioritize functional consistency over bespoke UX.
Key Concerns Identified:
- "Law of Leaky Abstractions": If complex workflow logic is encoded in JSON, config becomes a "poor man's programming language"
- Edge Cases (~10-20%): Some entities won't fit CRUD model (relationship editors, terminal windows, approval workflows)
- Type Safety: "JSON-like" is insufficient; must be strict TypeScript
Required Modifications:
- Strict TypeScript with Generics:
- Bad:
interface Column { key: string } - Good:
interface Column<T> { key: keyof T } - Use
satisfiesoperator or factory functions
- Bad:
- Accept Code, Not Just Data: Keep configs as
.ts/.tsxfiles to allow typed functions - Implement Escape Hatches (Slots Pattern):
- Slots:
BeforeList,DetailSidebar,CustomCellRenderer - Page Overrides: Bypass generator entirely for complex entities
- Slots:
- Feature Flag Contracts: If flag enabled (e.g.,
import: true), types must enforce supporting config - Centralized Registry: Typed registry of all entity configs to prevent magic strings
Modifications Applied
- Documented strict generics requirement
- Added escape hatch slots pattern
- Documented Zod runtime validation recommendation
- Added centralized typed registry pattern
Council Ranking
- All models reached strong consensus
- gpt-5.2: Best Response (type safety focus)
- claude-opus-4.5: Strong (escape hatches)
References
- Industry patterns: Strapi content types, Contentful models
docs/development/entity-development-guide.mddocs/AI_ENTITY_IMPLEMENTATION_GUIDE.md
ADR-016 | Frontend Layer | Implemented