contract-first-development.md

Comprehensive patterns for contract-first development in micro-block architecture with TypeScript interfaces and validation

contract-first-development.mdv1.0.015.4 KB
contract-first-development.md(markdown)
1# Contract-First Development Patterns
2
3## Overview
4
5Contract-First Development is a foundational principle of micro-block architecture where all interfaces, types, and contracts are defined before implementation. This enables AI agents to understand, compose, and substitute components safely.
6
7## Core Principles
8
91. **Define Before Implement**: Always define contracts before writing implementation code
102. **Explicit Contracts**: All inputs, outputs, and errors must have explicit TypeScript interfaces
113. **Version Compatibility**: Track both implementation and contract versions separately
124. **Self-Documenting**: Contracts serve as living documentation
135. **AI-Readable**: Rich metadata enables AI understanding and composition
14
15## Contract Definition Process
16
17### 1. Input Contract Design
18
19Define what data the command accepts:
20
21```typescript
22/**
23 * Input contract for creating a new user account
24 */
25interface CreateUserInput {
26  /** User's email address (must be valid email format) */
27  email: string;
28  
29  /** User's password (minimum 8 characters) */
30  password: string;
31  
32  /** User's display name */
33  name: string;
34  
35  /** Optional user profile information */
36  profile?: {
37    firstName?: string;
38    lastName?: string;
39    bio?: string;
40    avatarUrl?: string;
41  };
42  
43  /** Optional user preferences */
44  preferences?: {
45    emailNotifications: boolean;
46    language: string;
47    timezone: string;
48  };
49  
50  /** Optional metadata tags */
51  tags?: string[];
52}
53```
54
55### 2. Output Contract Design
56
57Define what data the command returns:
58
59```typescript
60/**
61 * Output contract for user creation result
62 */
63interface CreateUserOutput {
64  /** Unique identifier for the created user */
65  userId: string;
66  
67  /** User's email address */
68  email: string;
69  
70  /** User's display name */
71  name: string;
72  
73  /** Timestamp when user was created */
74  createdAt: Date;
75  
76  /** User's initial status */
77  status: 'active' | 'pending' | 'suspended';
78  
79  /** Whether email verification is required */
80  emailVerificationRequired: boolean;
81  
82  /** Links to related resources */
83  links: {
84    profile: string;
85    preferences: string;
86    avatar?: string;
87  };
88}
89```
90
91### 3. Error Contract Design
92
93Define specific error types with detailed information:
94
95```typescript
96/**
97 * Error contract for user creation failures
98 */
99class CreateUserError extends BaseError {
100  constructor(message: string, code?: string, details?: Record<string, any>) {
101    super(message, code, details);
102    Object.setPrototypeOf(this, CreateUserError.prototype);
103    this.name = "CreateUserError";
104  }
105  
106  /** Create validation error for invalid email */
107  static invalidEmail(email: string): CreateUserError {
108    const error = new CreateUserError(
109      'Email must be a valid email address format',
110      'INVALID_EMAIL'
111    );
112    error.setValidationError('email', 'input.email');
113    return error;
114  }
115  
116  /** Create error for password requirements */
117  static weakPassword(requirements: string[]): CreateUserError {
118    const error = new CreateUserError(
119      `Password must meet requirements: ${requirements.join(', ')}`,
120      'WEAK_PASSWORD',
121      { requirements }
122    );
123    error.setValidationError('password', 'input.password');
124    return error;
125  }
126  
127  /** Create error for duplicate email */
128  static emailExists(email: string): CreateUserError {
129    return new CreateUserError(
130      'A user with this email address already exists',
131      'EMAIL_EXISTS',
132      { email }
133    );
134  }
135}
136```
137
138## Service Contract Patterns
139
140### Service Interface Definition
141
142```typescript
143/**
144 * Database service contract for data persistence operations
145 */
146interface IDatabaseService extends BaseService {
147  /**
148   * Execute a query and return results
149   * @param query SQL query string with parameter placeholders
150   * @param params Parameters for the query
151   * @returns Array of result objects
152   */
153  query<T = any>(query: string, params?: Record<string, any>): Promise<T[]>;
154  
155  /**
156   * Execute a command (INSERT, UPDATE, DELETE)
157   * @param command SQL command string with parameter placeholders
158   * @param params Parameters for the command
159   * @returns Number of affected rows
160   */
161  execute(command: string, params?: Record<string, any>): Promise<number>;
162  
163  /**
164   * Execute multiple operations in a transaction
165   * @param operations Function containing operations to execute
166   * @returns Result of the transaction function
167   */
168  transaction<T>(operations: (tx: ITransactionContext) => Promise<T>): Promise<T>;
169  
170  /**
171   * Check if the database connection is healthy
172   * @returns True if connection is working
173   */
174  isHealthy(): Promise<boolean>;
175  
176  /**
177   * Get database connection statistics
178   * @returns Connection and performance statistics
179   */
180  getStats(): Promise<DatabaseStats>;
181}
182
183/**
184 * Configuration contract for database service
185 */
186interface DatabaseServiceConfig {
187  /** Database connection string */
188  connectionString: string;
189  
190  /** Maximum number of concurrent connections */
191  maxConnections: number;
192  
193  /** Connection timeout in milliseconds */
194  connectionTimeout: number;
195  
196  /** Number of retry attempts for failed connections */
197  retryAttempts: number;
198  
199  /** Whether to enable connection health monitoring */
200  enableHealthMonitoring: boolean;
201  
202  /** Query timeout in milliseconds */
203  queryTimeout: number;
204}
205
206/**
207 * Statistics contract for database service
208 */
209interface DatabaseStats {
210  /** Number of active connections */
211  activeConnections: number;
212  
213  /** Total number of queries executed */
214  totalQueries: number;
215  
216  /** Average query execution time in milliseconds */
217  averageQueryTime: number;
218  
219  /** Number of failed queries */
220  failedQueries: number;
221  
222  /** Last health check timestamp */
223  lastHealthCheck: Date;
224  
225  /** Whether the service is currently healthy */
226  isHealthy: boolean;
227}
228```
229
230### Service Metadata Contract
231
232```typescript
233/**
234 * Metadata contract for service discovery and selection
235 */
236interface ServiceMetadata {
237  /** Unique service identifier */
238  name: string;
239  
240  /** Human-readable display name */
241  displayName: string;
242  
243  /** Detailed description of service capabilities */
244  description: string;
245  
246  /** Interface contract this service implements */
247  contract: string;
248  
249  /** Implementation class name */
250  implementation: string;
251  
252  /** Service implementation version */
253  version: string;
254  
255  /** Contract version compatibility */
256  contractVersion: string;
257  
258  /** Key features and capabilities */
259  features: string[];
260  
261  /** Known limitations or constraints */
262  limitations: string[];
263  
264  /** External dependencies required */
265  requirements: string[];
266  
267  /** Optimal use cases and environments */
268  recommendations: string[];
269  
270  /** Service dependencies */
271  dependencies: {
272    /** Required service interfaces */
273    services: string[];
274  };
275  
276  /** Performance characteristics */
277  performance?: {
278    /** Expected response time category */
279    responseTime: 'fast' | 'moderate' | 'slow';
280    
281    /** Throughput characteristics */
282    throughput: 'high' | 'moderate' | 'low';
283    
284    /** Resource usage profile */
285    resourceUsage: 'light' | 'moderate' | 'heavy';
286  };
287  
288  /** Deployment characteristics */
289  deployment?: {
290    /** Deployment complexity */
291    complexity: 'simple' | 'moderate' | 'complex';
292    
293    /** Infrastructure requirements */
294    infrastructure: string[];
295    
296    /** Configuration requirements */
297    configuration: string[];
298  };
299}
300```
301
302## Command Contract Patterns
303
304### Command Metadata Contract
305
306```typescript
307/**
308 * Metadata contract for command discovery and composition
309 */
310interface CommandMetadata {
311  /** Unique command identifier */
312  name: string;
313  
314  /** Human-readable description */
315  description: string;
316  
317  /** Functional category for organization */
318  category: string;
319  
320  /** Input contract type name */
321  inputType: string;
322  
323  /** Output contract type name */
324  outputType: string;
325  
326  /** Error contract type name */
327  errorType: string;
328  
329  /** Command implementation version */
330  version: string;
331  
332  /** Input/output contract version */
333  contractVersion: string;
334  
335  /** Required permissions */
336  permissions?: string[];
337  
338  /** Execution timeout in milliseconds */
339  timeout?: number;
340  
341  /** Data flow specification */
342  dataFlow?: {
343    /** Input data fields */
344    inputs: string[];
345    
346    /** Output data fields */
347    outputs: string[];
348    
349    /** Side effects performed */
350    sideEffects: string[];
351  };
352  
353  /** Performance characteristics */
354  performance?: {
355    /** Expected execution duration */
356    expectedDuration: string;
357    
358    /** Performance scaling characteristics */
359    scaling: string;
360  };
361  
362  /** Dependency specification */
363  dependencies?: {
364    /** Service dependencies (e.g., IDatabaseService) */
365    services?: string[];
366    
367    /** Command dependencies (e.g., ValidateUserCommand) */
368    commands?: string[];
369    
370    /** External package dependencies (e.g., bcrypt, validator) */
371    external?: string[];
372  };
373  
374  /** AI composition hints */
375  composition?: {
376    /** Commands that commonly precede this one */
377    precedingCommands?: string[];
378    
379    /** Commands that commonly follow this one */
380    followingCommands?: string[];
381    
382    /** Alternative commands with similar functionality */
383    alternatives?: string[];
384  };
385}
386```
387
388## Contract Evolution Patterns
389
390### Version Compatibility
391
392```typescript
393/**
394 * Contract versioning follows semantic versioning principles
395 */
396
397// Version 1.0 - Initial contract
398interface CreateUserInputV1 {
399  email: string;
400  password: string;
401  name: string;
402}
403
404// Version 1.1 - Backward compatible addition
405interface CreateUserInputV1_1 {
406  email: string;
407  password: string;
408  name: string;
409  profile?: UserProfile;  // Optional addition - backward compatible
410}
411
412// Version 2.0 - Breaking change
413interface CreateUserInputV2 {
414  email: string;
415  password: string;
416  fullName: string;       // Breaking: 'name' renamed to 'fullName'
417  profile: UserProfile;   // Breaking: 'profile' now required
418}
419```
420
421### Contract Migration
422
423```typescript
424/**
425 * Contract migration utilities for handling version changes
426 */
427class ContractMigrator {
428  /**
429   * Migrate input from older version to current version
430   */
431  static migrateCreateUserInput(input: any, fromVersion: string): CreateUserInput {
432    switch (fromVersion) {
433      case '1.0':
434        return {
435          email: input.email,
436          password: input.password,
437          name: input.name,
438          profile: undefined  // Optional in v1.1+
439        };
440        
441      case '1.1':
442        return input; // Already compatible
443        
444      default:
445        throw new Error(`Unsupported contract version: ${fromVersion}`);
446    }
447  }
448}
449```
450
451## Contract Validation Patterns
452
453### Runtime Contract Validation
454
455```typescript
456/**
457 * Contract validation utilities
458 */
459class ContractValidator {
460  /**
461   * Validate input against contract
462   */
463  static validateCreateUserInput(input: any): CreateUserInput {
464    if (!input || typeof input !== 'object') {
465      throw new CreateUserError('Input must be an object', 'INVALID_INPUT');
466    }
467    
468    if (!input.email || typeof input.email !== 'string') {
469      throw CreateUserError.invalidEmail(input.email);
470    }
471    
472    if (!input.password || typeof input.password !== 'string') {
473      throw CreateUserError.weakPassword(['Must be a string']);
474    }
475    
476    if (!input.name || typeof input.name !== 'string') {
477      throw new CreateUserError('Name is required and must be a string', 'INVALID_NAME');
478    }
479    
480    return input as CreateUserInput;
481  }
482  
483  /**
484   * Validate output against contract
485   */
486  static validateCreateUserOutput(output: any): CreateUserOutput {
487    if (!output || typeof output !== 'object') {
488      throw new Error('Output must be an object');
489    }
490    
491    const required = ['userId', 'email', 'name', 'createdAt', 'status'];
492    for (const field of required) {
493      if (!(field in output)) {
494        throw new Error(`Output missing required field: ${field}`);
495      }
496    }
497    
498    return output as CreateUserOutput;
499  }
500}
501```
502
503## Contract Testing Patterns
504
505### Contract Compliance Testing
506
507```typescript
508describe('CreateUserCommand Contract Compliance', () => {
509  it('should accept valid input contract', () => {
510    const validInput: CreateUserInput = {
511      email: 'test@example.com',
512      password: 'securePassword123',
513      name: 'Test User'
514    };
515    
516    expect(() => ContractValidator.validateCreateUserInput(validInput)).not.toThrow();
517  });
518  
519  it('should reject invalid input contract', () => {
520    const invalidInput = {
521      email: 123,  // Should be string
522      password: 'password',
523      // name missing
524    };
525    
526    expect(() => ContractValidator.validateCreateUserInput(invalidInput)).toThrow();
527  });
528  
529  it('should return valid output contract', async () => {
530    const command = new CreateUserCommand(validInput, logger, services);
531    const output = await command.execute();
532    
533    expect(() => ContractValidator.validateCreateUserOutput(output)).not.toThrow();
534    expect(output.userId).toBeDefined();
535    expect(output.email).toBe(validInput.email);
536    expect(output.createdAt).toBeInstanceOf(Date);
537  });
538});
539```
540
541### Interface Compliance Testing
542
543```typescript
544describe('Service Contract Compliance', () => {
545  it('should implement IDatabaseService interface', () => {
546    const service = new DatabaseService(config, logger);
547    
548    // Verify method signatures
549    expect(typeof service.query).toBe('function');
550    expect(typeof service.execute).toBe('function');
551    expect(typeof service.transaction).toBe('function');
552    expect(typeof service.isHealthy).toBe('function');
553    
554    // Verify method arity (parameter count)
555    expect(service.query.length).toBe(2); // query, params
556    expect(service.execute.length).toBe(2); // command, params
557    expect(service.transaction.length).toBe(1); // operations
558    expect(service.isHealthy.length).toBe(0); // no parameters
559  });
560});
561```
562
563## Best Practices
564
565### Contract Design
5661. **Start with Contracts**: Define all interfaces before implementation
5672. **Rich Documentation**: Include detailed comments in contract definitions
5683. **Specific Types**: Use specific types instead of `any` or `unknown`
5694. **Optional vs Required**: Carefully consider which fields are optional
5705. **Future-Proofing**: Design contracts to allow backward-compatible evolution
571
572### Version Management
5731. **Semantic Versioning**: Follow semver for contract versions
5742. **Migration Support**: Provide migration utilities for breaking changes
5753. **Deprecation Notices**: Mark deprecated fields with clear alternatives
5764. **Compatibility Matrix**: Document which versions work together
5775. **Gradual Migration**: Support multiple versions during transition periods
578
579### Validation Strategy
5801. **Early Validation**: Validate contracts at command entry points
5812. **Comprehensive Testing**: Test all contract variations
5823. **Error Clarity**: Provide clear error messages for contract violations
5834. **Runtime Checks**: Include runtime validation for dynamic scenarios
5845. **Type Safety**: Use TypeScript's type system for compile-time validation
585
586### AI Enablement
5871. **Rich Metadata**: Include comprehensive metadata for AI understanding
5882. **Composition Hints**: Provide guidance for command composition
5893. **Alternative Options**: Document alternative commands with similar contracts
5904. **Performance Characteristics**: Include performance expectations
5915. **Usage Examples**: Provide examples of contract usage
592
593Contract-first development ensures that micro-block components have clear, well-defined interfaces that enable safe composition, substitution, and AI-driven selection while maintaining type safety and runtime validation.

Metadata

Path
utaba/main/patterns/micro-block/contract-first-development.md
Namespace
utaba/main/patterns/micro-block
Author
utaba
Category
patterns
Technology
typescript
Contract Version
1.0.0
MIME Type
text/markdown
Published
18-Jul-2025
Last Updated
18-Jul-2025