Hash-Based Schema Validation

Ensuring type safety and cache consistency with SHA-1 hashing

What is Hash Validation?

FlagFlow implements a sophisticated hash-based validation system that ensures your client-side TypeScript types remain in sync with server-side flag schemas. This prevents runtime errors and provides automatic cache invalidation when flag schemas change.

Core Concept: Each flag group has a unique SHA-1 hash based on its structure. When schemas change, hashes change, automatically invalidating outdated client code.

How Hash Validation Works

1. Hash Generation Process

FlagFlow generates SHA-1 hashes for each flag group using a combination of:

  • Flag names - The unique identifier for each flag
  • Flag types - The TypeScript type signature (boolean, number, enum, etc.)
  • Hierarchical structure - Group organization and nesting
  • Schema details - Enum values, constraints, and validation rules

2. Hierarchical Group Hashing

Flags are organized hierarchically using forward slashes as separators. Each level gets its own hash:

Hash Generation Example
// Example flag structure and their hashes
accounting/                    -> HASH_FLAGFLOW__ACCOUNTING
accounting/huf/                -> HASH_FLAGFLOW__ACCOUNTING__HUF
accounting/huf/allow_exchange  -> Individual flag in group

// Generated hash constants
export const HASH_FLAGFLOW = '2a3e205e597f33fd493563b6db4543a40e1ec986';
export const HASH_FLAGFLOW__ACCOUNTING = 'a004c5733c25be5995e918335aa777b1c5c0d4f4';
export const HASH_FLAGFLOW__ACCOUNTING__HUF = 'b12f456a789c012d345e678f901a234b567c890d';

3. Client-Server Hash Exchange

The validation process uses HTTP headers for hash exchange:

HeaderDirectionPurpose
x-accept-flaggroup-hashClient → ServerExpected hash from client's perspective
x-flaggroup-hashServer → ClientCurrent hash from server's perspective

Key Benefits

Type Safety

  • Prevents runtime type mismatches
  • Catches schema changes at request time
  • Ensures client code compatibility
  • Eliminates silent type errors

Automatic Cache Invalidation

  • No manual cache clearing needed
  • Instant detection of schema changes
  • Prevents stale data issues
  • Automatic client updates

Development Safety

  • Early error detection
  • Clear error messages
  • Prevents production issues
  • Team coordination made easy

Performance

  • Fast SHA-1 hash computation
  • Minimal network overhead
  • Efficient caching strategy
  • Reduced unnecessary requests

Implementation in Client Code

When you generate TypeScript definitions from FlagFlow, hash constants are automatically included for use in your client applications:

Generated Client Code with Hash Validation
import axios from "axios";
import { flagFlow_Descriptors, FlagFlow_DescriptorTypeMap } from "./flagflowTypes";

const FLAGFLOW_BASE_URL = 'http://localhost:3000/flags';

export const fetchData = async <K extends keyof FlagFlow_DescriptorTypeMap>(
    key: K
): Promise<FlagFlow_DescriptorTypeMap[K]> => {
    const { uri, hash } = flagFlow_Descriptors[key];
    const { data } = await axios.get<FlagFlow_DescriptorTypeMap[K]>(
        FLAGFLOW_BASE_URL + uri, {
        responseType: 'json',
        headers: {
            'Content-Type': 'application/json',
            'x-accept-flaggroup-hash': hash,  // <- Hash validation
        }
    })
    return data
}

Hash Descriptor Map

The generated TypeScript includes a descriptor map that connects flag groups to their URIs and hashes:

Generated Hash Descriptors
export const flagFlow_Descriptors = {
    '#root': { 
        uri: '/', 
        hash: HASH_FLAGFLOW 
    },
    'accounting': { 
        uri: '/accounting', 
        hash: HASH_FLAGFLOW__ACCOUNTING 
    },
    'accounting/huf': { 
        uri: '/accounting/huf', 
        hash: HASH_FLAGFLOW__ACCOUNTING__HUF 
    }
} as const;

Error Handling

409 Conflict Response

When hashes don't match, FlagFlow returns a 409 Conflict status with detailed information:

Hash Mismatch Error Response
// Server response when hashes don't match
HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "Hash mismatch detected",
  "details": {
    "expected": "2a3e205e597f33fd493563b6db4543a40e1ec986",
    "actual": "3b4f306f608g44ge504674c7ec5654b51f2fd097",
    "group": "accounting/huf",
    "message": "Flag schema has changed. Please update your TypeScript definitions."
  }
}

Client Error Handling

Recommended Error Handling
export const fetchDataWithErrorHandling = async <K extends keyof FlagFlow_DescriptorTypeMap>(
    key: K
): Promise<FlagFlow_DescriptorTypeMap[K]> => {
    try {
        return await fetchData(key);
    } catch (error) {
        if (error.response?.status === 409) {
            console.error('🚨 Schema hash mismatch!');
            console.error('Please regenerate your TypeScript definitions:');
            console.error('curl http://localhost:3000/type/typescript > flagflowTypes.ts');
            throw new Error('Flag schema out of date. Please update TypeScript definitions.');
        }
        throw error;
    }
}

Hash API Endpoints

FlagFlow provides dedicated endpoints for working with hashes:

EndpointDescriptionResponse
GET /type/hashGet hash map for all flag groupsJSON with group → hash mapping
GET /flags/[group]Get flag values with hash validationFlag data or 409 if hash mismatch
Hash Map API Response
// Get current hash map
curl http://localhost:3000/type/hash

// Response
{
  "#root": "2a3e205e597f33fd493563b6db4543a40e1ec986",
  "accounting": "a004c5733c25be5995e918335aa777b1c5c0d4f4",
  "accounting/huf": "b12f456a789c012d345e678f901a234b567c890d"
}

Best Practices

Development Workflow

  1. Always use hash validation - Include hash headers in all flag requests
  2. Handle 409 errors gracefully - Provide clear error messages to developers
  3. Automate type regeneration - Set up scripts to update TypeScript definitions
  4. Monitor hash changes - Track when schemas change in your CI/CD pipeline

Automation Scripts

Automated Type Update Script
#!/bin/bash
# update-flagflow-types.sh

echo "🔄 Checking for FlagFlow schema changes..."

# Download current TypeScript definitions
curl -s http://localhost:3000/type/typescript > flagflowTypes.new.ts

# Compare with existing file
if ! cmp -s flagflowTypes.ts flagflowTypes.new.ts; then
    echo "📝 Schema changes detected, updating types..."
    mv flagflowTypes.new.ts flagflowTypes.ts
    echo "✅ TypeScript definitions updated!"
else
    echo "✅ No schema changes detected."
    rm flagflowTypes.new.ts
fi

CI/CD Integration

CI/CD Schema Validation
# In your CI pipeline (e.g., GitHub Actions)
name: Check FlagFlow Schema
on: [push, pull_request]

jobs:
  check-flagflow:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Check FlagFlow schema sync
        run: |
          # Download current schema
          curl $FLAGFLOW_URL/type/typescript > current-schema.ts
          
          # Compare with committed version
          if ! cmp -s flagflowTypes.ts current-schema.ts; then
            echo "❌ FlagFlow schema out of sync!"
            echo "Run: curl $FLAGFLOW_URL/type/typescript > flagflowTypes.ts"
            exit 1
          fi
          
          echo "✅ FlagFlow schema is up to date"

Troubleshooting

Frequent 409 Errors

  • Check if flag schemas were recently modified
  • Regenerate TypeScript definitions from /type/typescript
  • Verify you're connecting to the correct FlagFlow instance
  • Clear any intermediate caches or proxies

Hash Generation Issues

  • Ensure flag names don't contain invalid characters
  • Check for duplicate flag names in the same group
  • Verify enum values are properly formatted
  • Look for circular dependencies in flag hierarchies

Client-Side Debugging

  • Log hash values being sent in headers
  • Compare client hash with server response
  • Check network tab for actual HTTP headers
  • Verify TypeScript definitions are properly imported
© 2025 FlagFlow All Rights Reserved. llms.txt