-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Context
During PR #78 review, GitHub Copilot identified a recurring pattern in the codebase: runtime validation of data despite TypeScript's type guarantees. This pattern is used throughout the codebase but lacks formal documentation explaining when and why it's necessary.
Current Usage
The pattern appears in multiple locations:
-
Persona Validator (
packages/ums-lib/src/core/validation/persona-validator.ts:88-92):// Runtime validation required: persona data comes from external files (YAML/JSON) // which may not conform to TypeScript types. TypeScript provides compile-time safety // only - we must validate at runtime to catch malformed input data. // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!entry || typeof entry !== 'object') {
-
TypeScript Loader (
packages/copilot-instructions-cli/src/utils/typescript-loader.ts):- Type guards:
isModuleLike(),isPersonaLike() - Runtime checks for dynamically imported modules
- Type guards:
Problem
Without formal documentation:
- Developers may question why runtime checks exist alongside TypeScript types
- ESLint rules need disabling without clear justification
- The pattern may be inconsistently applied across the codebase
- New contributors lack guidance on when to use this pattern
Proposed Solution
Create an Architecture Decision Record (ADR) that documents:
1. Decision
When and why to perform runtime validation despite TypeScript type guarantees
2. Context
- External data sources (YAML, JSON, user input)
- Dynamic imports with unknown shape
- TypeScript's compile-time vs runtime guarantees
- Trust boundaries in the application
3. Rationale
- TypeScript provides compile-time type safety only
- External data may not conform to declared types
- Dynamic imports bypass compile-time checks
- Defense in depth for data integrity
4. Consequences
Positive:
- Robust error handling at trust boundaries
- Clear validation failures with helpful messages
- Protection against malformed external data
- Explicit trust boundary documentation
Negative:
- Code duplication between types and runtime checks
- ESLint rule suppressions needed
- Slight performance overhead
- More verbose code
5. Guidelines
When to use runtime validation:
- Loading data from files (YAML, JSON, etc.)
- Processing user input
- Dynamic imports of unknown modules
- API responses from external services
- Any data crossing trust boundaries
When NOT to use:
- Internal function parameters within the same package
- Data already validated earlier in the call chain
- Performance-critical hot paths with trusted data
Acceptance Criteria
- ADR created in
docs/adr/directory - Follow standard ADR template (if one exists)
- Document the pattern with code examples
- Reference existing implementations
- Provide clear guidelines for when to apply
- Link from main documentation
References
- PR feat: Implement UMS v2.0 with TypeScript support #78: feat: Implement UMS v2.0 with TypeScript support #78
- Copilot comment on persona-validator.ts
- Existing architecture_principles.md in docs/archive/
Priority
Medium - Documentation improvement for consistency and maintainability