ATOM Documentation

← Back to App

Frontend-Backend Unification Guide

**Phase:** 298 - Frontend-Backend Unification & Redundancy Removal

**Last Updated:** 2026-04-12

---

Overview

This guide explains how to achieve frontend-backend unification, remove redundant code, prevent bugs, and establish regression prevention mechanisms.

Goals

  1. **API Contract Testing:** Validate frontend-backend API alignment
  2. **Redundancy Removal:** Eliminate duplicate code across boundaries
  3. **Bug Prevention:** Discover and fix integration bugs early
  4. **Type Safety:** Enforce type safety across API boundaries
  5. **Quality Gates:** Prevent regressions with automated checks

Key Principles

  • **Backend is Single Source of Truth:** Validation, business rules, and data transformations live in the backend
  • **Frontend is UX-Only:** Frontend validation is for user experience only (format hints, real-time feedback)
  • **Type Safety:** No any types in API layer - all types must be explicit
  • **Contract Testing:** All API endpoints must have contract tests
  • **Regression Prevention:** Quality gates prevent breaking changes

---

API Contract Testing

What is Contract Testing?

Contract testing validates that frontend and backend APIs are aligned:

  • Request parameters match
  • Response structures match
  • Type mappings are correct (TypeScript ↔ Python)
  • Auth/tenant requirements are consistent

How to Write Contract Tests

Backend Contract Tests (Python)

# backend-saas/api/__tests__/contract/agent_routes_contract.py
from fastapi.testclient import TestClient
from main_api_app import app

client = TestClient(app)

def test_list_agents_contract():
    """Test GET /api/agents contract"""
    response = client.get(
        "/api/agents",
        headers={"Authorization": "Bearer test-token"}
    )

    assert response.status_code == 200
    data = response.json()

    # Verify response structure
    assert "agents" in data
    assert isinstance(data["agents"], list)

    # Verify agent structure
    if len(data["agents"]) > 0:
        agent = data["agents"][0]
        assert "id" in agent
        assert "name" in agent
        assert "maturity" in agent
        assert isinstance(agent["capabilities"], list)

Frontend Contract Tests (TypeScript)

// src/lib/api/__tests__/contract-tests/agent-api-contracts.test.ts
import { describe, it, expect } from 'vitest';
import { fetchAgents } from '@/lib/api/agents';

describe('Agent API Contracts', () => {
  it('should return agents with correct structure', async () => {
    const response = await fetchAgents();

    // Verify response structure
    expect(response).toHaveProperty('agents');
    expect(Array.isArray(response.agents)).toBe(true);

    // Verify agent structure
    if (response.agents.length > 0) {
      const agent = response.agents[0];
      expect(agent).toHaveProperty('id');
      expect(agent).toHaveProperty('name');
      expect(agent).toHaveProperty('maturity');
      expect(Array.isArray(agent.capabilities)).toBe(true);
    }
  });
});

Type Mapping Rules

TypeScriptPythonExample
stringstr, UUID, datetime, EmailStrAgent ID
numberint, float, DecimalACU usage
booleanboolActive status
Array<T>List[T]Capabilities list
ObjectDict, JSONSettings object
DatedatetimeCreated at

Running Contract Tests

# Backend contract tests
cd backend-saas && pytest api/__tests__/contract/

# Frontend contract tests
npm test -- src/lib/api/__tests__/contract-tests/

---

Redundancy Detection and Removal

What is Redundancy?

Redundancy is duplicate code across frontend and backend:

  • Duplicate validation logic (email regex, password rules)
  • Duplicate data transformations (date formatting, currency rounding)
  • Duplicate business rules (agent limits, quota checks)

How to Detect Redundancy

Run Redundancy Detection Script

cd backend-saas
python3 scripts/detect_redundancy.py \
  --frontend ../src \
  --backend . \
  --output .planning/phases/298-frontend-backend-unification

Manual Inspection

# Find duplicate validation logic
grep -r "email.*regex" src/ backend-saas/

# Find duplicate date formatting
grep -r "toISOString\|strftime" src/ backend-saas/

# Find duplicate business rules
grep -r "agent.*limit\|quota.*check" src/ backend-saas/

How to Remove Redundancy

1. Keep Backend Only

**Before (Redundant):**

// src/lib/validation/email.ts (frontend)
export function validateEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}
# backend-saas/core/validation.py (backend)
def validate_email(email: str) -> bool:
    email_regex = re.compile(r'^[^\s@]+@[^\s@]+\.[^\s@]+$')
    return bool(email_regex.match(email))

**After (Backend Only):**

// src/lib/validation/email.ts (frontend)
// Re-export from backend validation
// Backend is single source of truth
export const validateEmail = (email: string): boolean => {
  // Backend validates this - frontend only checks format for UX
  return email.includes('@'); // Simple UX check only
};
# backend-saas/core/validation.py (backend)
def validate_email(email: str) -> bool:
    """Validate email address (single source of truth)"""
    email_regex = re.compile(r'^[^\s@]+@[^\s@]+\.[^\s@]+$')
    return bool(email_regex.match(email))

2. Remove Frontend Transformations

**Before (Redundant):**

// src/lib/api/agents.ts (frontend)
const response = await fetch('/api/agents');
const data = await response.json();
// Transform date format
data.agents.forEach(agent => {
  agent.createdAt = new Date(agent.created_at).toISOString();
});

**After (Backend Provides Display-Ready Data):**

// src/lib/api/agents.ts (frontend)
const response = await fetch('/api/agents');
const data = await response.json();
// No transformation needed - backend provides display-ready data
# backend-saas/api/agent_routes.py (backend)
@router.get("/api/agents")
async def list_agents(tenant_id: str):
    agents = await db.query(Agent).filter(Agent.tenant_id == tenant_id).all()
    return {
        "agents": [
            {
                "id": str(agent.id),
                "name": agent.name,
                "createdAt": agent.created_at.isoformat(),  # Display-ready
            }
            for agent in agents
        ]
    }

3. Remove Frontend Business Rules

**Before (Redundant):**

// src/lib/api/agents.ts (frontend)
const plan = await fetchPlan();
const agentCount = await fetchAgentCount();
if (agentCount >= plan.agentLimit) {
  throw new Error('Agent limit exceeded');
}

**After (Backend Enforces Rules):**

// src/lib/api/agents.ts (frontend)
// Just try to create agent - backend will enforce limit
const response = await fetch('/api/agents', {
  method: 'POST',
  body: JSON.stringify({ name: 'New Agent' })
});
if (!response.ok) {
  const error = await response.json();
  if (error.code === 'AGENT_LIMIT_EXCEEDED') {
    // Show user-friendly message
    alert(error.message);
  }
}

---

Type Safety Enforcement

Why Type Safety Matters

Type safety prevents bugs at compile time:

  • Catches type mismatches early
  • Improves IDE autocomplete
  • Self-documenting code
  • Prevents data corruption at API boundaries

No `any` Types Rule

**❌ Bad (Uses any):**

async function createAgent(data: any): Promise<any> {
  const response = await fetch('/api/agents', {
    method: 'POST',
    body: JSON.stringify(data)
  });
  return await response.json();
}

**✅ Good (Explicit Types):**

interface CreateAgentRequest {
  name: string;
  maturity: 'student' | 'intern' | 'supervised' | 'autonomous';
  capabilities: string[];
}

interface AgentResponse {
  id: string;
  name: string;
  maturity: string;
  capabilities: string[];
  createdAt: string;
}

async function createAgent(data: CreateAgentRequest): Promise<AgentResponse> {
  const response = await fetch('/api/agents', {
    method: 'POST',
    body: JSON.stringify(data)
  });
  return await response.json();
}

Exception: `error: any`

The only acceptable use of any is in catch blocks:

try {
  await riskyOperation();
} catch (error: any) {
  // error: any is acceptable here
  console.error(error.message);
}

Pre-commit Hook Enforcement

The pre-commit hook automatically checks for any types:

# Commit will be blocked if `any` types found
git commit -m "feat: add API endpoint"
# ❌ Error: Found 5 instances of `any` type in API layer

---

Regression Prevention

CI/CD Quality Gates

The .github/workflows/regression-prevention.yml workflow runs on:

  • Every pull request
  • Every push to main
  • Daily scheduled run (2 AM UTC)

Quality Checks

  1. **Coverage >= 90%:** Both frontend and backend must have 90%+ test coverage
  2. **Duplication < 5%:** Code duplication must be below 5%
  3. **Type Safety:** No any types in API layer
  4. **Contract Tests:** All contract tests must pass
  5. **Integration Tests:** All integration tests must pass

Pre-commit Hooks

# Runs automatically on every commit
git commit -m "feat: add feature"

# Checks:
# ✅ No `any` types in API layer
# ✅ Python coverage for billing/quota files

Quality Metrics Monitoring

Track quality metrics over time:

import { qualityMetricsAPI } from '@/lib/monitoring/quality-metrics';

// Get current metrics
const report = await qualityMetricsAPI.getCurrentMetrics();
console.log('Overall score:', report.overallScore);
console.log('Recommendations:', report.recommendations);

// Check for regressions
const regressions = await qualityMetricsAPI.checkRegressions();
if (regressions.length > 0) {
  console.error('Regressions detected:', regressions);
}

---

Troubleshooting

Common Issues

1. Pre-commit Hook Fails

**Error:** Found 5 instances of 'any' type in API layer

**Solution:** Replace any with proper types

// Before
function processData(data: any): any { ... }

// After
interface DataInput {
  id: string;
  value: number;
}

interface DataOutput {
  result: string;
}

function processData(data: DataInput): DataOutput { ... }

2. Coverage Check Fails

**Error:** Backend coverage 85% is below 90% threshold

**Solution:** Add tests for uncovered code

# View coverage report
open backend-saas/htmlcov/index.html

# Find uncovered files
cd backend-saas && coverage report --show-missing

3. Contract Test Fails

**Error:** Agent API contract test failed: Expected 'id' to be string

**Solution:** Fix type mismatch

# Backend: Return UUID as string
@router.get("/api/agents/{agent_id}")
async def get_agent(agent_id: UUID):
    agent = await db.get_agent(agent_id)
    return {
        "id": str(agent.id),  # Convert UUID to string
        "name": agent.name,
    }

4. Duplication Check Fails

**Error:** Code duplication 8% exceeds 5% threshold

**Solution:** Remove duplicate code

# Run redundancy detection
cd backend-saas
python3 scripts/detect_redundancy.py \
  --frontend ../src \
  --backend . \
  --output .planning/phases/298-frontend-backend-unification

# Review report
cat .planning/phases/298-frontend-backend-unification/redundancy-report.md

# Remove duplicates

---

Best Practices

1. Backend is Single Source of Truth

  • ✅ Keep validation logic in backend
  • ✅ Keep business rules in backend
  • ✅ Keep data transformations in backend
  • ❌ Don't duplicate in frontend

2. Frontend is UX-Only

  • ✅ Frontend validation for format hints
  • ✅ Frontend validation for real-time feedback
  • ✅ Frontend validation for user experience
  • ❌ Don't enforce business rules in frontend

3. Type Safety First

  • ✅ Always use explicit types
  • ✅ Never use any (except error: any)
  • ✅ Define interfaces for API contracts
  • ❌ Don't skip type checking

4. Test Everything

  • ✅ Write contract tests for all APIs
  • ✅ Write integration tests for workflows
  • ✅ Write property-based tests for critical logic
  • ✅ Write fuzz tests for input validation
  • ❌ Don't skip testing

5. Prevent Regressions

  • ✅ Run pre-commit hooks
  • ✅ Fix CI/CD failures immediately
  • ✅ Monitor quality metrics
  • ✅ Address regressions early
  • ❌ Don't ignore quality gates

---

Additional Resources

Documentation

Scripts

  • backend-saas/scripts/verify-phase-298.py - Comprehensive verification
  • backend-saas/scripts/detect_redundancy.py - Redundancy detection

Workflows

  • .github/workflows/regression-prevention.yml - CI/CD quality gates
  • .husky/pre-commit - Pre-commit quality checks

Monitoring

  • src/lib/monitoring/quality-metrics.ts - Quality metrics API
  • backend-saas/core/monitoring/quality_metrics.py - Quality metrics collector

---

**Last Updated:** 2026-04-12

**Phase:** 298 - Frontend-Backend Unification

**Status:** 90% Complete