Implemented complete Human-in-the-Loop approval workflow for AI-proposed changes:
Changes:
- Created PendingChange DTOs (PendingChangeDto, CreatePendingChangeRequest, ApproveChangeRequest, RejectChangeRequest, PendingChangeFilterDto)
- Implemented IPendingChangeService interface with CRUD, approval/rejection, expiration, and deletion operations
- Implemented PendingChangeService with full workflow support and tenant isolation
- Created McpPendingChangesController REST API with endpoints for listing, approving, rejecting, and deleting pending changes
- Implemented PendingChangeApprovedEventHandler to execute approved changes via MediatR commands (Project, Epic, Story, Task CRUD operations)
- Created PendingChangeExpirationBackgroundService for auto-expiration of changes after 24 hours
- Registered all services and background service in DI container
Technical Details:
- Status flow: PendingApproval → Approved → Applied (or Rejected/Expired)
- Tenant isolation enforced in all operations
- Domain events published for audit trail
- Event-driven execution using MediatR
- Background service runs every 5 minutes to expire old changes
- JWT authentication required for all endpoints
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement comprehensive Diff Preview Service to show changes before AI operations.
This is the core safety mechanism for M2, enabling transparency and user approval.
Domain Layer:
- Enhanced DiffPreviewService with HTML diff generation
- Added GenerateHtmlDiff() for visual change representation
- Added FormatValue() to handle dates, nulls, and long strings
- HTML output includes XSS protection with HtmlEncode
Application Layer:
- Created DiffPreviewDto and DiffFieldDto for API responses
- DTOs support JSON serialization for REST APIs
Infrastructure Layer:
- Created PendingChangeRepository with all query methods
- Created TaskLockRepository with resource locking support
- Added PendingChangeConfiguration (EF Core) with JSONB storage
- Added TaskLockConfiguration (EF Core) with unique indexes
- Updated McpDbContext with new entities
- Created EF migration AddPendingChangeAndTaskLock
Database Schema:
- pending_changes table with JSONB diff column
- task_locks table with resource locking
- Indexes for tenant_id, api_key_id, status, created_at, expires_at
- Composite indexes for performance optimization
Service Registration:
- Registered DiffPreviewService in DI container
- Registered TaskLockService in DI container
- Registered PendingChangeRepository and TaskLockRepository
Tests:
- Created DiffPreviewServiceTests with core scenarios
- Tests cover CREATE, UPDATE, and DELETE operations
- Tests verify HTML diff generation and XSS protection
Technical Highlights:
- DiffPreview stored as JSONB using value converter
- HTML diff with color-coded changes (green/red/yellow)
- Field-level diff comparison using reflection
- Truncates long values (>500 chars) for display
- Type-safe enum conversions for status fields
Story: Sprint 5, Story 5.9 - Diff Preview Service Implementation
Priority: P0 CRITICAL
Story Points: 5 (2 days)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive API Key authentication and management system
for MCP Server to ensure only authorized AI agents can access ColaFlow.
## Domain Layer
- Created McpApiKey aggregate root with BCrypt password hashing
- Implemented ApiKeyPermissions value object (read/write, resource/tool filtering)
- Added ApiKeyStatus enum (Active, Revoked)
- Created domain events (ApiKeyCreatedEvent, ApiKeyRevokedEvent)
- API key format: cola_<36 random chars> (cryptographically secure)
- Default expiration: 90 days
## Application Layer
- Implemented McpApiKeyService with full CRUD operations
- Created DTOs for API key creation, validation, and updates
- Validation logic: hash verification, expiration check, IP whitelist
- Usage tracking: last_used_at, usage_count
## Infrastructure Layer
- Created McpDbContext with PostgreSQL configuration
- EF Core entity configuration with JSONB for permissions/IP whitelist
- Implemented McpApiKeyRepository with prefix-based lookup
- Database migration: mcp_api_keys table with indexes
- Created McpApiKeyAuthenticationMiddleware for API key validation
- Middleware validates Authorization: Bearer <api_key> header
## API Layer
- Created McpApiKeysController with REST endpoints:
- POST /api/mcp/keys - Create API Key (returns plain key once!)
- GET /api/mcp/keys - List tenant's API Keys
- GET /api/mcp/keys/{id} - Get API Key details
- PATCH /api/mcp/keys/{id}/metadata - Update name/description
- PATCH /api/mcp/keys/{id}/permissions - Update permissions
- DELETE /api/mcp/keys/{id} - Revoke API Key
- Requires JWT authentication (not API key auth)
## Testing
- Created 17 unit tests for McpApiKey entity
- Created 7 unit tests for ApiKeyPermissions value object
- All 49 tests passing (including existing MCP tests)
- Test coverage > 80% for Domain layer
## Security Features
- BCrypt hashing with work factor 12
- API key shown only once at creation (never logged)
- Key prefix lookup for fast validation (indexed)
- Multi-tenant isolation (tenant_id filter)
- IP whitelist support
- Permission scopes (read/write, resources, tools)
- Automatic expiration after 90 days
## Database Schema
Table: mcp.mcp_api_keys
- Indexes: key_prefix (unique), tenant_id, tenant_user, expires_at, status
- JSONB columns for permissions and IP whitelist
- Soft delete via revoked_at
## Integration
- Updated Program.cs to register MCP module with configuration
- Added MCP DbContext migration in development mode
- Authentication middleware runs before MCP protocol handler
Changes:
- Created 31 new files (2321+ lines)
- Domain: 6 files (McpApiKey, events, repository, value objects)
- Application: 9 files (service, DTOs)
- Infrastructure: 8 files (DbContext, repository, middleware, migration)
- API: 1 file (McpApiKeysController)
- Tests: 2 files (17 + 7 unit tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>