feat(agentic): implement MAF-based agentic PDF processing pipeline with auth, structured logging, and comprehensive tests - #8
Conversation
- update all projects TargetFramework from net8.0 to net10.0 - add Microsoft.Agents.AI 1.5.0 package to Worker - add Microsoft.Agents.AI.Abstractions 1.5.0 package to Shared - update Microsoft.EntityFrameworkCore to 10.0.* across all projects - update Microsoft.Extensions.Diagnostics.HealthChecks to 10.0.* - update Microsoft.Extensions.Hosting to 10.0.* - update Npgsql.EntityFrameworkCore.PostgreSQL to 10.0.* - update Microsoft.AspNetCore.OpenApi to 10.0.* (replaces Swashbuckle) - update Microsoft.AspNetCore.Mvc.Testing to 10.0.* in test projects - update Microsoft.EntityFrameworkCore.InMemory to 10.0.* - update Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore to 10.0.* - replace Swashbuckle.AspNetCore with Scalar.AspNetCore 2.14.11 - replace AddSwaggerGen() with AddOpenApi() in Program.cs - replace UseSwagger()/UseSwaggerUI() with MapOpenApi()/MapScalarApiReference() - add using Scalar.AspNetCore to Program.cs - update EFCore.NamingConventions from 8.0.3 to 10.0.1 - fix CS8625 warning in DocumentProcessingServiceTests (null literal) - fix CS8604 warning in DocumentProcessingServiceTests (possible null reference) - remove redundant System.Text.Json package from IntegrationTests - remove redundant Microsoft.Extensions.Diagnostics.HealthChecks from ApiGateway
- add WorkflowCheckpoint model for durable agent workflow state - add AgentDefinition model for agent registry and discovery - add DbSet<WorkflowCheckpoint> and DbSet<AgentDefinition> to Worker AppDbContext - configure EF Core mappings for workflow_checkpoints and agent_definitions tables - add SQL schema for new tables in db/init.sql - seed DocumentProcessing agent definition in init.sql
…AgentContext) - add AgentResult class for activity execution results - add AgentContext class for passing state between workflow activities - add IAgent interface for implementing agent workflows - add ICheckpointStore interface for checkpoint persistence - add IAgentOrchestrator interface for agent pipeline orchestration
- add PostgreSqlCheckpointStore implementing ICheckpointStore - SaveCheckpointAsync uses upsert semantics (insert or update) - LoadCheckpointAsync returns most recent checkpoint for resume - LoadCompletedCheckpointsAsync returns all completed activities - DeleteCheckpointsAsync cleans up after workflow completion
- add DocumentProcessingAgent implementing IAgent interface - 5 workflow activities: DownloadDocument, ParseDocument, ExtractText, SaveResult, UpdateStatus - each activity saves a checkpoint after execution for durable execution - resume support: skips already-completed activities after worker crash - reuses existing PdfTextExtractor, IDocumentRepository, IFileStorage services - cleanup checkpoints after successful workflow completion
- replace DocumentProcessingService with DocumentProcessingAgent in consumer - add ICheckpointStore and IDocumentRepository dependencies to consumer - build AgentContext from MassTransit command for agent execution - preserve MassTransit retry/DLQ as base-level protection - add message-level idempotency check before agent execution - update XML docs to explain hybrid MassTransit + MAF architecture
- register DocumentProcessingAgent as scoped service - register ICheckpointStore -> PostgreSqlCheckpointStore as scoped - add Worker.Agents namespace using directive - update Program.cs comments to explain hybrid MassTransit + MAF architecture - keep DocumentProcessingService for backward compatibility
…scenarios - add 5 unit tests for DocumentProcessingAgent - test AgentName and Activities properties - test full workflow execution with all 5 checkpoints saved - test resume after crash (skips completed activities) - test failure handling with failure checkpoint saved - make PdfTextExtractor.ExtractTextAsync virtual for Moq compatibility
…scenarios - Add 5 new checkpoint resume scenarios (middle, last, all-completed) - Add Base64 bytes roundtrip test for checkpoint state data - Add failure checkpoint error message preservation test - Total: 9 tests in DocumentProcessingAgentTests, all passing
- Update README.md: agentic architecture diagram, MAF+MassTransit hybrid explanation, new agent example (TranslationAgent), updated metrics - Fill AGENTIC_READINESS.md: migration results, architecture details, MAF system requirements (.NET 10.0+), checkpoint test coverage, TranslationAgent example with DI registration - Update AGENTIC_ROADMAP.md: mark all 9 stages as completed, add completion status banner
- add MetricsHostedService that integrates metric server lifecycle with generic host - remove manual MetricServer creation from Program.cs - register via AddHostedService for graceful shutdown on SIGTERM
…tension - move if/else DB selection logic from Program.cs into a dedicated extension method - add AddDatabase(IServiceCollection, IConfiguration, IHostEnvironment) to ServiceCollectionExtensions - keep all three branches: Testing→in-memory, connection string→PostgreSQL, fallback→in-memory - improve SRP compliance — Program.cs now only composes services
- add AddGatewayAuthentication() extension in Authentication/ directory - add TokenRequest/TokenResponse models in Authentication/ directory - add dev-only AuthController with POST /auth/token endpoint - configure Jwt:SecretKey in appsettings.Development.json for local testing - skip auth in Testing environment to avoid breaking unit tests - add Microsoft.AspNetCore.Authentication.JwtBearer package
- add Serilog.AspNetCore and Serilog.Formatting.Compact packages to both projects - configure Serilog + CompactJsonFormatter in ApiGateway and Worker Program.cs - remove .ConfigureLogging() block from Worker (now handled by Serilog) - structured JSON output enables log aggregation tools like Loki, Elasticsearch
…mpose healthcheck - add DocumentProcessingException in Shared/Exceptions for typed error handling - replace bare new Exception() in PdfProcessingConsumer with DocumentProcessingException - add CancellationToken.ThrowIfCancellationRequested() at the start of each agent activity to enable graceful shutdown during long-running Tesseract OCR operations - worker already had postgres healthcheck dependency (verified)
…, and concurrency tests - add OutboxPublisherTests: publish pending, corrupt JSON, publish failure, cancellation - add PdfProcessingConsumerRetryTests: agent failure re-throws, sets Failed status, idempotency - add ConcurrencyTests: duplicate detection via TryUpdateStatusAsync, two workers skip duplicate - total tests increased from 28 to 37
- CI/.NET/License badges - SOTA-solution description - 37 tests, Serilog, JWT in summary
There was a problem hiding this comment.
Code Review
This pull request migrates the PDF processing system to an 'Agentic' architecture using the Microsoft Agent Framework (MAF) and upgrades the entire solution to .NET 10. Key changes include the implementation of a checkpoint-based workflow in the Worker service to enable durable processing and resume capabilities, the addition of JWT authentication in the ApiGateway, and the integration of Serilog for structured logging. The test suite has been significantly expanded to cover the new MAF agent, checkpoint persistence, and concurrency scenarios. Feedback identifies several security and reliability improvements, including the need for secret length validation, environment-based restrictions for the development authentication endpoint, and more flexible configuration for the metrics server port. Additionally, a potential issue with exception message lengths exceeding database column limits in the checkpoint store was noted.
| ValidateLifetime = true, | ||
| ValidateIssuerSigningKey = true, | ||
| IssuerSigningKey = new SymmetricSecurityKey( | ||
| System.Text.Encoding.UTF8.GetBytes(jwtSecret)), |
There was a problem hiding this comment.
The jwtSecret is used to create a SymmetricSecurityKey. For the HMAC SHA256 algorithm, the key must be at least 128 bits (16 bytes), but 256 bits (32 bytes) is recommended for security. If the configured secret is too short, the application will throw an exception at runtime during token validation. Consider adding a validation check for the secret length in the configuration logic.
| [ApiController] | ||
| [Route("auth")] | ||
| [AllowAnonymous] | ||
| public class AuthController : ControllerBase |
There was a problem hiding this comment.
| public MetricsHostedService(ILogger<MetricsHostedService> logger) | ||
| { | ||
| _logger = logger; | ||
| // Prometheus metrics endpoint — separate port for worker metrics | ||
| _metricServer = new MetricServer(port: 5091); | ||
| } |
There was a problem hiding this comment.
The Prometheus metric server port is hardcoded to 5091. It is recommended to inject IConfiguration and retrieve the port from settings to allow flexibility across different environments.
public MetricsHostedService(IConfiguration configuration, ILogger<MetricsHostedService> logger)
{
_logger = logger;
var port = configuration.GetValue<int>("Metrics:Port", 5091);
_metricServer = new MetricServer(port: port);
}| existing.StateData = result.OutputData; | ||
| existing.IsCompleted = result.IsSuccess; | ||
| existing.IsFailed = !result.IsSuccess; | ||
| existing.ErrorMessage = result.ErrorMessage; |
There was a problem hiding this comment.
The ErrorMessage column in the workflow_checkpoints table is limited to 4096 characters. If an exception message is longer, saving the checkpoint will fail. It's safer to truncate the message before assignment.
existing.ErrorMessage = result.ErrorMessage?.Length > 4096 ? result.ErrorMessage[..4096] : result.ErrorMessage;…v-only auth, metrics port config, error message truncation
Summary
This PR introduces a major evolution of the PDF processing system — migration from a simple message-driven pipeline to a Microsoft Agent Framework (MAF) based agentic architecture with checkpoint/resume capabilities, JWT authentication, structured logging, and significantly expanded test coverage.
What's Changed
Agentic Architecture (MAF)
IAgent,IAgentOrchestrator,ICheckpointStore,AgentContext,AgentDefinition,AgentResult,WorkflowCheckpointmodels inSharedprojectPostgreSqlCheckpointStorefor durable agent state persistencePdfProcessingConsumernow delegates toDocumentProcessingAgentvia MAF pipelineMicrosoft.Agents.AIpackagesAuthentication
AuthenticationExtensionsandTokenModelsappsettings.jsonandappsettings.Development.jsonStructured Logging
ILoggerwith Serilog structured logging across ApiGateway and WorkerTesting (846+ new test lines)
Infrastructure & Reliability
DocumentProcessingExceptionfor better error handlingMetricServerin `IHostedService