Part 4 of 5: Mastering complex business rules, contract composition, and bulletproof testing
Welcome back! In Part 3, we built a complete Next.js user management system. Today, we're diving deep into advanced contract patterns that handle the most complex business scenarios and ensure your AI-generated code remains bulletproof.
๐งฉ Contract Composition and Inheritance
Real applications need flexible, reusable contracts. Let's build a system that can handle complex combinations:
Base Contract Templates
// lib/contracts/templates.ts
// Common contract building blocks
export const baseUserContract = {
requires: [auth('user')],
ensures: [auditLog('user_operation')]
};
export const adminUserContract = {
requires: [auth('admin'), rateLimit('admin_operation', 20)],
ensures: [auditLog('admin_operation')]
};
export const ownershipContract = (resourceField: string) => ({
requires: [owns(resourceField)],
ensures: [auditLog(`${resourceField}_access`)]
});
// Contract composition function
export function composeContracts(...contracts: Partial<ContractOptions>[]): ContractOptions {
return {
requires: contracts.flatMap(c => c.requires || []),
ensures: contracts.flatMap(c => c.ensures || []),
invariants: contracts.flatMap(c => c.invariants || []),
layer: contracts.find(c => c.layer)?.layer
};
}
// Pre-built contract combinations
export const ContractTemplates = {
// Standard CRUD operations
userCRUD: (requiredRole: string = 'user') => composeContracts(
baseUserContract,
{
requires: [validates(userUpdateSchema), owns('userId')],
ensures: [returns(userOutputSchema)]
}
),
// Admin-only operations
adminOnly: (operation: string) => composeContracts(
adminUserContract,
{
requires: [validates(z.any())],
ensures: [returns(z.any())]
}
),
// Public API (no auth required)
publicAPI: (operation: string, schema: z.ZodSchema) => ({
requires: [validates(schema), rateLimit(`public_${operation}`, 100)],
ensures: [auditLog(`public_${operation}`)]
}),
// Bulk operations
bulkOperation: (itemContract: ContractOptions) => ({
requires: [
auth('admin'),
(input: any[]) => {
if (!Array.isArray(input)) {
throw new ContractError('INVALID_BULK_INPUT', 'Input must be an array');
}
if (input.length > 1000) {
throw new ContractError('BATCH_TOO_LARGE', 'Batch size must be โค 1000 items');
}
return true;
}
],
ensures: [auditLog('batch_operation')]
})
};
Using Contract Composition
// lib/services/posts.ts
class PostService {
// Combining multiple contract concerns
@contract(composeContracts(
baseUserContract,
ownershipContract('postId'),
{
requires: [validates(postUpdateSchema)],
ensures: [returns(postOutputSchema)],
invariants: [(input, output) => output.id === input.postId]
}
))
async updatePost(input: PostUpdateInput, context: AuthContext): Promise<Post> {
// Implementation
}
// Using pre-built templates
@contract(ContractTemplates.adminOnly('deleteAnyPost'))
async adminDeletePost(input: { postId: string }, context: AuthContext): Promise<void> {
// Implementation
}
}
๐ Conditional Contracts
Sometimes contracts need to adapt based on context. Here's how to build dynamic contracts:
// lib/contracts/conditional.ts
export function conditionalContract(
condition: (input: any, context: any) => boolean,
whenTrue: ContractOptions,
whenFalse: ContractOptions = {}
): MethodDecorator {
return function(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function(...args: any[]) {
const [input, context] = args;
const contractToApply = condition(input, context) ? whenTrue : whenFalse;
// Apply the selected contract
const contractDecorator = contract(contractToApply);
const tempDescriptor = { value: originalMethod };
contractDecorator(target, propertyName, tempDescriptor);
return tempDescriptor.value.apply(this, args);
};
return descriptor;
};
}
// Usage examples
class UserService {
// Different contracts based on role change
@conditionalContract(
(input, context) => input.role && input.role !== context.user.roles[0],
// Role change requires admin privileges
{
requires: [auth('admin'), businessRule('Role change requires admin', () => true)],
ensures: [auditLog('role_change')]
},
// Normal profile update
{
requires: [auth('user'), owns('userId')],
ensures: [auditLog('profile_update')]
}
)
async updateUser(input: UserUpdateInput, context: AuthContext): Promise<User> {
// Implementation adapts automatically
}
// Time-based contracts
@conditionalContract(
(input, context) => {
const hour = new Date().getHours();
return hour >= 9 && hour <= 17; // Business hours
},
// Business hours: normal rate limit
{ requires: [rateLimit('createUser', 10)] },
// Off hours: stricter rate limit
{ requires: [rateLimit('createUser', 3)] }
)
async createUser(input: UserCreateInput, context: AuthContext): Promise<User> {
// Rate limiting adapts to time of day
}
}
๐ Bulk Operation Contracts
Handling arrays of data safely:
// lib/contracts/bulk.ts
export function bulkContract(itemContract: ContractOptions): ContractOptions {
return {
requires: [
// Validate input is array
(input: any[], context: AuthContext) => {
if (!Array.isArray(input)) {
throw new ContractError('INVALID_BULK_INPUT', 'Input must be an array');
}
if (input.length === 0) {
throw new ContractError('EMPTY_BULK_INPUT', 'Input array cannot be empty');
}
if (input.length > 1000) {
throw new ContractError('BULK_TOO_LARGE', 'Batch size must be โค 1000 items');
}
return true;
},
// Apply item-level requires to each item
async (input: any[], context: AuthContext) => {
for (let i = 0; i < input.length; i++) {
try {
for (const condition of itemContract.requires || []) {
if (typeof condition === 'function' && condition.length === 1) {
input[i] = condition(input[i]);
} else {
await condition(input[i], context);
}
}
} catch (error) {
throw new ContractError('BULK_ITEM_VALIDATION_FAILED',
`Item ${i} failed validation: ${error.message}`);
}
}
return true;
}
],
ensures: [
// Apply item-level ensures to each result
async (output: any[], input: any[], context: AuthContext) => {
for (let i = 0; i < output.length; i++) {
for (const condition of itemContract.ensures || []) {
await condition(output[i], input[i], context);
}
}
return true;
}
]
};
}
// Usage
class UserService {
@contract(bulkContract({
requires: [owns('userId'), validates(userUpdateSchema)],
ensures: [auditLog('bulk_user_update'), returns(userOutputSchema)]
}))
async bulkUpdateUsers(users: UserUpdateInput[], context: AuthContext): Promise<User[]> {
const results = [];
for (const user of users) {
results.push(await this.updateUser(user, context));
}
return results;
}
}
๐ Advanced Debugging and Monitoring
Contract Execution Visualization
// lib/contracts/debug.ts
interface ContractExecution {
contractName: string;
layer: string;
timestamp: Date;
input: any;
output?: any;
status: 'success' | 'failure';
error?: any;
duration: number;
}
class ContractDebugger {
private static executions: ContractExecution[] = [];
private static isEnabled = process.env.NODE_ENV === 'development';
static logExecution(
contractName: string,
layer: string,
input: any,
output?: any,
error?: any,
duration?: number
) {
if (!this.isEnabled) return;
const execution: ContractExecution = {
contractName,
layer,
timestamp: new Date(),
input: this.sanitizeForLog(input),
output: this.sanitizeForLog(output),
status: error ? 'failure' : 'success',
error: error?.message,
duration: duration || 0
};
this.executions.push(execution);
// Real-time console output
const icon = error ? 'โ' : 'โ
';
const timeStr = duration ? ` (${duration.toFixed(2)}ms)` : '';
console.log(`${icon} Contract [${layer}] ${contractName}${timeStr}`, {
input: execution.input,
...(output && { output: execution.output }),
...(error && { error: error.message })
});
// Keep only last 1000 executions
if (this.executions.length > 1000) {
this.executions = this.executions.slice(-1000);
}
}
static getExecutionReport(): {
summary: {
total: number;
success: number;
failure: number;
successRate: string;
avgDuration: number;
};
byLayer: Record<string, { success: number; failure: number; avgDuration: number }>;
recentFailures: ContractExecution[];
} {
const total = this.executions.length;
const successes = this.executions.filter(e => e.status === 'success');
const failures = this.executions.filter(e => e.status === 'failure');
const avgDuration = this.executions.reduce((sum, e) => sum + e.duration, 0) / total;
const byLayer = this.executions.reduce((acc, e) => {
if (!acc[e.layer]) {
acc[e.layer] = { success: 0, failure: 0, durations: [] };
}
acc[e.layer][e.status]++;
acc[e.layer].durations.push(e.duration);
return acc;
}, {} as any);
// Calculate averages
Object.keys(byLayer).forEach(layer => {
const durations = byLayer[layer].durations;
byLayer[layer].avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
delete byLayer[layer].durations;
});
return {
summary: {
total,
success: successes.length,
failure: failures.length,
successRate: `${((successes.length / total) * 100).toFixed(1)}%`,
avgDuration: parseFloat(avgDuration.toFixed(2))
},
byLayer,
recentFailures: failures.slice(-10)
};
}
private static sanitizeForLog(data: any): any {
if (typeof data !== 'object' || data === null) return data;
const sanitized = { ...data };
delete sanitized.password;
delete sanitized.token;
delete sanitized.secret;
return sanitized;
}
}
// Enhanced contract decorator with debugging
export function debuggableContract(options: ContractOptions) {
return function(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const contractName = `${target.constructor.name}.${propertyName}`;
descriptor.value = async function(...args: any[]) {
const startTime = performance.now();
const [input, context] = args;
try {
// Apply all contract conditions
let validatedInput = input;
for (const condition of options.requires || []) {
if (typeof condition === 'function' && condition.length === 1) {
validatedInput = condition(validatedInput);
} else {
await condition(validatedInput, context);
}
}
const result = await originalMethod.call(this, validatedInput, context);
for (const condition of options.ensures || []) {
await condition(result, validatedInput, context);
}
for (const invariant of options.invariants || []) {
if (!invariant(validatedInput, result)) {
throw new ContractError('INVARIANT_VIOLATION',
`Invariant condition failed in ${contractName}`);
}
}
const duration = performance.now() - startTime;
ContractDebugger.logExecution(contractName, options.layer || 'unknown', input, result, null, duration);
return result;
} catch (error) {
const duration = performance.now() - startTime;
ContractDebugger.logExecution(contractName, options.layer || 'unknown', input, null, error, duration);
throw new ContractViolationError(contractName, options.layer || 'unknown', error);
}
};
return descriptor;
};
}
// Make debugger available globally in development
if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {
(window as any).__contractDebugger = ContractDebugger;
}
๐งช Comprehensive Testing Strategies
Contract Unit Testing
// __tests__/contracts.test.ts
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
import { auth, owns, validates, rateLimit } from '@/lib/contracts';
import { userUpdateSchema } from '@/lib/schemas/user';
describe('Contract Conditions', () => {
let mockContext: AuthContext;
beforeEach(() => {
mockContext = {
user: { id: 'user-123', email: 'test@example.com', roles: ['user'] },
session: { id: 'session-123', expiresAt: new Date(Date.now() + 3600000) }
};
});
describe('auth condition', () => {
it('should pass with valid user and role', async () => {
const authCondition = auth('user');
await expect(authCondition({}, mockContext)).resolves.toBe(true);
});
it('should fail with insufficient role', async () => {
const authCondition = auth('admin');
await expect(authCondition({}, mockContext))
.rejects
.toThrow('Required role: admin');
});
it('should fail with expired session', async () => {
mockContext.session.expiresAt = new Date(Date.now() - 1000);
const authCondition = auth('user');
await expect(authCondition({}, mockContext))
.rejects
.toThrow('Session has expired');
});
it('should fail with no user', async () => {
mockContext.user = null as any;
const authCondition = auth('user');
await expect(authCondition({}, mockContext))
.rejects
.toThrow('User must be logged in');
});
});
describe('owns condition', () => {
beforeEach(() => {
jest.spyOn(global, 'getResourceById').mockImplementation(async (id) => {
const resources = {
'resource-123': { id: 'resource-123', userId: 'user-123' },
'resource-456': { id: 'resource-456', userId: 'user-456' }
};
return resources[id] || null;
});
});
it('should pass for resource owner', async () => {
const ownsCondition = owns('resourceId');
await expect(ownsCondition({ resourceId: 'resource-123' }, mockContext))
.resolves.toBe(true);
});
it('should pass for admin', async () => {
mockContext.user.roles = ['admin'];
const ownsCondition = owns('resourceId');
await expect(ownsCondition({ resourceId: 'resource-456' }, mockContext))
.resolves.toBe(true);
});
it('should fail for non-owner', async () => {
const ownsCondition = owns('resourceId');
await expect(ownsCondition({ resourceId: 'resource-456' }, mockContext))
.rejects
.toThrow('does not own resource');
});
it('should fail with missing resource ID', async () => {
const ownsCondition = owns('resourceId');
await expect(ownsCondition({}, mockContext))
.rejects
.toThrow('Field resourceId is required');
});
});
describe('validates condition', () => {
it('should pass with valid input', () => {
const validatesCondition = validates(userUpdateSchema);
const validInput = {
userId: '123e4567-e89b-12d3-a456-426614174000',
email: 'test@example.com',
name: 'Test User'
};
expect(() => validatesCondition(validInput)).not.toThrow();
});
it('should fail with invalid email', () => {
const validatesCondition = validates(userUpdateSchema);
const invalidInput = {
userId: '123e4567-e89b-12d3-a456-426614174000',
email: 'invalid-email',
name: 'Test User'
};
expect(() => validatesCondition(invalidInput))
.toThrow('Input validation failed');
});
it('should fail with invalid UUID', () => {
const validatesCondition = validates(userUpdateSchema);
const invalidInput = {
userId: 'not-a-uuid',
email: 'test@example.com',
name: 'Test User'
};
expect(() => validatesCondition(invalidInput))
.toThrow('Invalid user ID format');
});
});
describe('rateLimit condition', () => {
beforeEach(() => {
// Reset rate limit store
jest.clearAllMocks();
});
it('should pass under rate limit', async () => {
const rateLimitCondition = rateLimit('testOperation', 5);
await expect(rateLimitCondition({}, mockContext)).resolves.toBe(true);
});
it('should fail when rate limit exceeded', async () => {
const rateLimitCondition = rateLimit('testOperation', 1);
// First call should succeed
await expect(rateLimitCondition({}, mockContext)).resolves.toBe(true);
// Second call should fail
await expect(rateLimitCondition({}, mockContext))
.rejects
.toThrow('Rate limit exceeded');
});
});
});
Integration Testing with Contracts
// __tests__/user-service.integration.test.ts
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
import { UserService } from '@/lib/services/users';
import { ContractViolationError } from '@/lib/contracts';
import { userRepository } from '@/lib/data/users';
describe('UserService Integration', () => {
let userService: UserService;
let mockContext: AuthContext;
beforeEach(() => {
userService = new UserService();
mockContext = {
user: { id: 'user-123', email: 'user@test.com', roles: ['user'] },
session: { id: 'session-123', expiresAt: new Date(Date.now() + 3600000) }
};
// Mock repository methods
jest.spyOn(userRepository, 'findById').mockResolvedValue({
id: 'user-123',
email: 'user@test.com',
name: 'Test User',
role: 'user',
createdAt: new Date(),
updatedAt: new Date()
});
jest.spyOn(userRepository, 'save').mockImplementation(async (user) => ({
...user,
updatedAt: new Date()
}));
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('updateUser', () => {
it('should successfully update own profile', async () => {
const input = {
userId: 'user-123',
email: 'newemail@test.com',
name: 'New Name'
};
const result = await userService.updateUser(input, mockContext);
expect(result.email).toBe('newemail@test.com');
expect(result.name).toBe('New Name');
expect(userRepository.save).toHaveBeenCalledWith(
expect.objectContaining({
email: 'newemail@test.com',
name: 'New Name'
}),
mockContext
);
});
it('should fail when trying to update other user profile', async () => {
const input = {
userId: 'user-456', // Different user
email: 'newemail@test.com',
name: 'New Name'
};
await expect(userService.updateUser(input, mockContext))
.rejects
.toThrow(ContractViolationError);
});
it('should prevent role change by non-admin', async () => {
const input = {
userId: 'user-123',
role: 'admin' // Trying to escalate privileges
};
await expect(userService.updateUser(input, mockContext))
.rejects
.toThrow('Cannot change own role');
});
it('should allow admin to change roles', async () => {
mockContext.user.roles = ['admin'];
const input = {
userId: 'user-123',
role: 'moderator'
};
const result = await userService.updateUser(input, mockContext);
expect(result.role).toBe('moderator');
});
it('should enforce email change frequency limit', async () => {
// Mock user with recent email change
jest.spyOn(userRepository, 'findById').mockResolvedValue({
id: 'user-123',
email: 'old@test.com',
name: 'Test User',
role: 'user',
createdAt: new Date(),
updatedAt: new Date(),
emailChangedAt: new Date() // Changed today
});
const input = {
userId: 'user-123',
email: 'new@test.com'
};
await expect(userService.updateUser(input, mockContext))
.rejects
.toThrow('Email change frequency limit');
});
});
describe('createUser', () => {
beforeEach(() => {
mockContext.user.roles = ['admin']; // Admin required for user creation
jest.spyOn(userRepository, 'findByEmail').mockResolvedValue(null); // No duplicate
jest.spyOn(userRepository, 'create').mockImplementation(async (user) => user);
});
it('should successfully create user as admin', async () => {
const input = {
email: 'newuser@test.com',
name: 'New User',
role: 'user' as const
};
const result = await userService.createUser(input, mockContext);
expect(result.email).toBe('newuser@test.com');
expect(result.name).toBe('New User');
expect(result.role).toBe('user');
});
it('should fail when non-admin tries to create user', async () => {
mockContext.user.roles = ['user'];
const input = {
email: 'newuser@test.com',
name: 'New User',
role: 'user' as const
};
await expect(userService.createUser(input, mockContext))
.rejects
.toThrow('Required role: admin');
});
it('should fail with duplicate email', async () => {
jest.spyOn(userRepository, 'findByEmail').mockResolvedValue({
id: 'existing-user',
email: 'duplicate@test.com',
name: 'Existing User',
role: 'user',
createdAt: new Date(),
updatedAt: new Date()
});
const input = {
email: 'duplicate@test.com',
name: 'New User',
role: 'user' as const
};
await expect(userService.createUser(input, mockContext))
.rejects
.toThrow('Email must be unique');
});
});
});
Contract Mock System
// __tests__/helpers/contract-mocker.ts
export class ContractMocker {
private originalConditions = new Map<string, any>();
private mocks = new Map<string, any>();
mockCondition(conditionName: string, result: any) {
this.mocks.set(conditionName, result);
}
mockAuth(result: boolean | Error) {
this.mockCondition('auth', result);
}
mockOwnership(result: boolean | Error) {
this.mockCondition('owns', result);
}
mockValidation(result: any | Error) {
this.mockCondition('validates', result);
}
mockRateLimit(result: boolean | Error) {
this.mockCondition('rateLimit', result);
}
applyMocks() {
// Store originals
this.originalConditions.set('auth', global.auth);
this.originalConditions.set('owns', global.owns);
this.originalConditions.set('validates', global.validates);
this.originalConditions.set('rateLimit', global.rateLimit);
// Apply mocks
global.auth = () => async () => {
const mock = this.mocks.get('auth');
if (mock instanceof Error) throw mock;
return mock ?? true;
};
global.owns = () => async () => {
const mock = this.mocks.get('owns');
if (mock instanceof Error) throw mock;
return mock ?? true;
};
global.validates = () => (input: any) => {
const mock = this.mocks.get('validates');
if (mock instanceof Error) throw mock;
return mock ?? input;
};
global.rateLimit = () => async () => {
const mock = this.mocks.get('rateLimit');
if (mock instanceof Error) throw mock;
return mock ?? true;
};
return this.restoreMocks.bind(this);
}
restoreMocks() {
// Restore originals
this.originalConditions.forEach((original, name) => {
(global as any)[name] = original;
});
this.originalConditions.clear();
this.mocks.clear();
}
}
// Usage in tests
describe('Contract Mocking', () => {
let contractMocker: ContractMocker;
let restoreMocks: () => void;
beforeEach(() => {
contractMocker = new ContractMocker();
restoreMocks = contractMocker.applyMocks();
});
afterEach(() => {
restoreMocks();
});
it('should handle auth failure gracefully', async () => {
contractMocker.mockAuth(new ContractError('AUTH_FAILED', 'Mock auth failure'));
await expect(userService.updateUser(validInput, mockContext))
.rejects
.toThrow('Mock auth failure');
});
it('should bypass rate limiting in tests', async () => {
contractMocker.mockRateLimit(true);
// Can now test business logic without rate limit interference
const result = await userService.updateUser(validInput, mockContext);
expect(result).toBeDefined();
});
});
๐ Performance Optimization
Contract Compilation and Caching
// lib/contracts/performance.ts
interface CompiledContract {
staticChecks: Function[];
dynamicChecks: Function[];
postConditions: Function[];
invariants: Function[];
}
class ContractOptimizer {
private static contractCache = new Map<string, CompiledContract>();
private static conditionCache = new Map<string, any>();
static compileContract(contractName: string, options: ContractOptions): CompiledContract {
if (this.contractCache.has(contractName)) {
return this.contractCache.get(contractName)!;
}
const compiled = this.optimizeContract(options);
this.contractCache.set(contractName, compiled);
return compiled;
}
private static optimizeContract(options: ContractOptions): CompiledContract {
const requires = options.requires || [];
return {
staticChecks: this.extractStaticChecks(requires),
dynamicChecks: this.extractDynamicChecks(requires),
postConditions: options.ensures || [],
invariants: options.invariants || []
};
}
private static extractStaticChecks(conditions: any[]): Function[] {
return conditions.filter(c =>
typeof c === 'function' &&
c.length === 1 && // Validators take only input
!c.toString().includes('await') &&
!c.toString().includes('async')
);
}
private static extractDynamicChecks(conditions: any[]): Function[] {
return conditions.filter(c =>
typeof c === 'function' && (
c.length === 2 || // Conditions take input + context
c.toString().includes('await') ||
c.toString().includes('async')
)
);
}
// Schema compilation and caching
static getCachedValidator(schemaKey: string, schema: z.ZodSchema) {
if (!this.conditionCache.has(schemaKey)) {
const compiledValidator = schema.parse.bind(schema);
this.conditionCache.set(schemaKey, compiledValidator);
}
return this.conditionCache.get(schemaKey);
}
static clearCache() {
this.contractCache.clear();
this.conditionCache.clear();
}
}
// Optimized contract decorator
export function optimizedContract(options: ContractOptions) {
return function(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const contractName = `${target.constructor.name}.${propertyName}`;
const compiled = ContractOptimizer.compileContract(contractName, options);
descriptor.value = async function(...args: any[]) {
const [input, context] = args;
try {
// Static checks first (fastest)
let validatedInput = input;
for (const check of compiled.staticChecks) {
validatedInput = check(validatedInput);
}
// Dynamic checks (slower, but necessary)
for (const check of compiled.dynamicChecks) {
await check(validatedInput, context);
}
// Execute original method
const result = await originalMethod.call(this, validatedInput, context);
// Post-conditions
for (const condition of compiled.postConditions) {
await condition(result, validatedInput, context);
}
// Invariants
for (const invariant of compiled.invariants) {
if (!invariant(validatedInput, result)) {
throw new ContractError('INVARIANT_VIOLATION',
`Invariant failed in ${contractName}`);
}
}
return result;
} catch (error) {
throw new ContractViolationError(contractName, options.layer || 'unknown', error);
}
};
return descriptor;
};
}
๐ฏ AI-Friendly Development Patterns
Smart Contract Generation
// lib/contracts/ai-helpers.ts
// AI can use this to auto-generate appropriate contracts
export function smartContract(options: {
operation: 'create' | 'read' | 'update' | 'delete';
resource: string;
visibility: 'public' | 'private' | 'admin';
rateLimit?: number;
customRules?: string[];
}): ContractOptions {
const contracts: ContractOptions = {
requires: [],
ensures: [],
invariants: []
};
// Visibility-based auth requirements
switch (options.visibility) {
case 'public':
// No auth required
break;
case 'private':
contracts.requires!.push(auth('user'));
if (options.operation !== 'create') {
contracts.requires!.push(owns(`${options.resource}Id`));
}
break;
case 'admin':
contracts.requires!.push(auth('admin'));
break;
}
// Operation-based validation
if (['create', 'update'].includes(options.operation)) {
contracts.requires!.push(
validates(getSchemaForResource(options.resource, options.operation))
);
}
// Rate limiting
if (options.rateLimit) {
contracts.requires!.push(
rateLimit(`${options.operation}_${options.resource}`, options.rateLimit)
);
}
// Always audit
contracts.ensures!.push(
auditLog(`${options.operation}_${options.resource}`)
);
// Output validation for data-returning operations
if (['create', 'read', 'update'].includes(options.operation)) {
contracts.ensures!.push(
returns(getSchemaForResource(options.resource, 'output'))
);
}
return contracts;
}
function getSchemaForResource(resource: string, operation: string): z.ZodSchema {
const schemas: Record<string, Record<string, z.ZodSchema>> = {
user: {
create: userCreateSchema,
update: userUpdateSchema,
output: userOutputSchema
},
post: {
create: postCreateSchema,
update: postUpdateSchema,
output: postOutputSchema
}
// Add more resources as needed
};
return schemas[resource]?.[operation] || z.any();
}
// Example AI usage
class AIGeneratedController {
// AI prompt: "Create a user profile update endpoint"
@contract(smartContract({
operation: 'update',
resource: 'user',
visibility: 'private',
rateLimit: 5
}))
async updateUserProfile(input: UserUpdateInput, context: AuthContext) {
return userService.updateUser(input, context);
}
// AI prompt: "Create an admin user deletion endpoint"
@contract(smartContract({
operation: 'delete',
resource: 'user',
visibility: 'admin',
rateLimit: 10
}))
async deleteUser(input: { userId: string }, context: AuthContext) {
return userService.deleteUser(input.userId, context);
}
}
๐ What We've Mastered
In this part, we've covered:
โ
Contract Composition - Reusable, composable security patterns
โ
Conditional Contracts - Dynamic security based on context
โ
Bulk Operations - Safe handling of array data
โ
Advanced Debugging - Real-time contract execution monitoring
โ
Comprehensive Testing - Unit tests, integration tests, and mocking
โ
Performance Optimization - Contract compilation and caching
โ
AI-Friendly Patterns - Smart contract generation for AI tools
๐ฎ Coming in Part 5
In our final installment, we'll explore:
- Production deployment strategies
- AI template libraries that make secure code the default
- Monitoring and alerting for contract violations
- The future of AI-assisted development
Questions about the advanced patterns? Drop them in the comments! I love seeing how you adapt these to your specific use cases.
Next: The final chapter where we deploy this system to production and build an AI-friendly template library.
Top comments (0)