Skip to content

Create ADR for Runtime Validation Pattern #86

@synthable

Description

@synthable

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:

  1. 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') {
  2. TypeScript Loader (packages/copilot-instructions-cli/src/utils/typescript-loader.ts):

    • Type guards: isModuleLike(), isPersonaLike()
    • Runtime checks for dynamically imported modules

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

Priority

Medium - Documentation improvement for consistency and maintainability

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions