Skip to content

Phase 3: Migrate Template Functions to Type-Safe Go Methods for Performance & Maintainability #86

Description

@coderabbitai

🎯 Phase 3 of Programmatic Markdown Generation Refactor

Parent Issue: #73 | Milestone: v2.0 | Type: Breaking Change

📖 Context

opnDossier currently uses Go templates with custom template functions (via Sprig) to generate markdown reports from OPNsense configuration data. While functional, this approach has several limitations:

Current Pain Points

  • ⚠️ Runtime errors: Template parsing errors only caught at runtime
  • 🐌 Performance overhead: Template parsing adds ~45% execution time
  • 🔧 Limited IDE support: No IntelliSense or type checking for template functions
  • 🧪 Testing complexity: Difficult to unit test individual template functions
  • 📚 Maintenance burden: Dual code paths (template + programmatic)
  • 🔍 Debugging difficulty: Template stack traces are cryptic

The Opportunity

By migrating all custom template functions to type-safe Go methods on the MarkdownBuilder, we gain:

  • Compile-time safety: Catch errors during build, not at runtime
  • Performance: 30-50% faster report generation (no template parsing)
  • 🛠️ Developer experience: Full IDE support with IntelliSense and debugging
  • 🧪 Testability: Unit test each method independently
  • 📦 Maintainability: Single, clean code path

🔍 Current State Analysis

Template Functions Inventory

The codebase currently has 20+ custom template functions in internal/markdown/generator.go:

Utility Functions:

  • escapeTableContent - Escape markdown table special characters
  • boolToString - Convert boolean to enabled/disabled
  • formatBytes - Human-readable byte formatting
  • truncate - String truncation with ellipsis
  • sanitizeID - Create markdown-safe IDs

Data Transformation:

  • filterTunables - Filter system tunables by security relevance
  • groupServicesByStatus - Group services by running/stopped
  • filterRulesByType - Filter firewall rules by type
  • aggregatePackageStats - Calculate package statistics

Security Assessment:

  • getRiskLevel - Assess and format security risk levels
  • calculateSecurityScore - Overall security posture scoring
  • assessServiceRisk - Per-service risk evaluation

Complex Formatters:

  • formatInterfacesAsLinks - Generate markdown links for interfaces
  • formatSystemStats - System statistics aggregation
  • formatNetworkInterfaces - Network interface table formatting
  • formatFirewallRules - Firewall rule table generation
  • formatServices - Service status formatting
  • formatUsers - User account table generation
  • formatPackages - Package list formatting
  • formatCertificates - Certificate information display

💡 Proposed Solution

Architecture

┌─────────────────────────────────────────────────────┐
│           OpnSense XML Configuration                │
└────────────────┬────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────┐
│              XML Parser (existing)                  │
└────────────────┬────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────┐
│          Data Model (model.OpnSenseDocument)        │
└────────────────┬────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────┐
│         MarkdownBuilder (Type-Safe Methods)         │
│  ┌────────────────────────────────────────────────┐ │
│  │ • FormatInterfaceLinks()                       │ │
│  │ • AssessRiskLevel()                            │ │
│  │ • FilterSystemTunables()                       │ │
│  │ • CalculateSecurityScore()                     │ │
│  │ • FormatNetworkInterfaces()                    │ │
│  │ • (All 20+ methods)                            │ │
│  └────────────────────────────────────────────────┘ │
└────────────────┬────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────┐
│            Markdown Report Output                   │
└─────────────────────────────────────────────────────┘

Implementation Strategy

This phase is broken into 10 detailed subtasks for systematic implementation:

📋 Planning & Mapping

🔧 Core Function Migration

✅ Testing & Validation

🚀 Integration & Documentation

Implementation Example

Before (Template):

{{ define "interfaces" }}
## Network Interfaces
Configured: {{ .interfaces | formatInterfacesAsLinks }}
Risk Level: {{ getRiskLevel .security.level }}
{{ end }}

After (Programmatic):

func (b *MarkdownBuilder) WriteInterfacesSection(data *model.OpnSenseDocument) {
    b.WriteHeader(2, "Network Interfaces")
    
    interfaceLinks := b.FormatInterfaceLinks(data.Interfaces)
    b.WriteParagraph("Configured: " + interfaceLinks)
    
    riskLevel := b.AssessRiskLevel(data.Security.Level)
    b.WriteParagraph("Risk Level: " + riskLevel)
}

📅 Implementation Timeline

Week 1: Core Migration

Week 2: Testing & Validation

Week 3: Integration & Documentation

✅ Acceptance Criteria

Functional Requirements

  • All 20+ template functions ported to MarkdownBuilder methods
  • Each method has proper Go documentation with examples
  • Zero runtime template parsing in default mode
  • Template mode still available via --use-template flag
  • Full backward compatibility for existing workflows

Quality Requirements

  • 90%+ test coverage for all ported methods
  • 100% coverage for security assessment functions
  • All edge cases tested (empty data, nil values, special characters)
  • Integration tests validate functional parity with templates

Performance Requirements

  • 30-50% reduction in report generation time
  • 20-30% reduction in memory allocations
  • Benchmarks documented and tracked

Documentation Requirements

  • API documentation for all builder methods
  • Migration guide with examples
  • Architecture documentation updated
  • Deprecation timeline clearly communicated

🎯 Success Metrics

Performance Targets

  • Execution Time: 30-50% faster than template mode
  • Memory Usage: 20-30% reduction in allocations
  • Build Time: Errors caught at compile-time

Quality Targets

  • Test Coverage: >90% overall, 100% for security functions
  • Bug Reduction: Eliminate runtime template errors
  • Developer Velocity: Faster feature development with IDE support

Adoption Targets

  • Default Usage: Programmatic mode used by default
  • Migration: Clear path for custom template users
  • Deprecation: Template mode removed by v3.0

🔗 Dependencies

Prerequisite Phases

  • Phase 1: Core refactoring (assumed complete)
  • Phase 2: Builder infrastructure (assumed complete)

Blocking Issues

  • None - ready to begin implementation

Related Work

🏷️ Breaking Changes (v2.0)

⚠️ This is a breaking change for users with custom templates:

  1. Default Behavior Change

    • Before: Templates used by default
    • After: Programmatic generation by default
    • Migration: Add --use-template flag
  2. Template Function Removal

    • Custom template functions deprecated
    • Will be removed in v3.0
    • Use MarkdownBuilder methods instead
  3. API Changes

📚 Additional Resources


Note: This issue tracks the overall Phase 3 effort. Implementation work is split across subtasks #89-98. Please reference the appropriate subtask when contributing.

Metadata

Metadata

Assignees

Labels

breaking_changeSignificant changes that disrupt backward compatibility.enhancementNew feature or requestgoPull requests that update go codeperformancePerformance optimization and improvementspriority:highHigh priority issuetestingTest infrastructure and test-related issues

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions