Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
13 KiB
Tasks: Implement Web API
Phase 1: Project Setup
-
001: Create JdeScoping.Api project
- Location:
NEW/src/JdeScoping.Api/JdeScoping.Api.csproj - Dependencies: Microsoft.AspNetCore.Authentication.Cookies, System.DirectoryServices.Protocols, Swashbuckle.AspNetCore, ClosedXML
- Validation:
dotnet buildsucceeds
- Location:
-
002: Add project reference to JdeScoping.Host
- Location:
NEW/src/JdeScoping.Host/JdeScoping.Host.csproj - Validation: Solution builds with new reference
- Location:
-
003: Create configuration option classes
- LdapOptions:
NEW/src/JdeScoping.Api/Configuration/LdapOptions.cs - AuthOptions:
NEW/src/JdeScoping.Api/Configuration/AuthOptions.cs - Properties per design.md specification
- Validation: Options bind from appsettings.json
- LdapOptions:
Phase 2: Data Models
-
004: Create UserInfo model
- Location:
NEW/src/JdeScoping.Core/Models/UserInfo.cs - Source:
OLD/DataModel/Models/LDAPEntry.cs - Include computed DisplayName property
- Validation: Model compiles with correct properties
- Note: Updated existing model with DN property
- Location:
-
005: Create StatusUpdate model
- Location:
NEW/src/JdeScoping.Core/Models/StatusUpdate.cs - Source:
OLD/DataModel/Models/StatusUpdate.cs - Properties: Message, Timestamp
- Validation: Model compiles
- Note: Already existed in Core project
- Location:
-
006: Create SearchUpdate model
- Location:
NEW/src/JdeScoping.Core/Models/SearchUpdate.cs - Source:
OLD/DataModel/Models/SearchUpdate.cs - Include JsonStringEnumConverter for Status
- Validation: Model compiles with JSON serialization working
- Note: Already existed in Core project
- Location:
-
007: Create LoginRequest model
- Location:
NEW/src/JdeScoping.Api/Models/LoginRequest.cs - Source:
OLD/WebInterface/Models/LogonRequest.cs - Include Required attributes for validation
- Validation: Model compiles
- Location:
-
008: Create AuthResult record
- Location:
NEW/src/JdeScoping.Api/Models/AuthResult.cs - Properties: Success, User, ErrorMessage
- Validation: Record compiles
- Location:
-
009: Create FileUploadResult model
- Location:
NEW/src/JdeScoping.Api/Models/FileUploadResult.cs - Source:
OLD/WebInterface/Models/FileUploadResult.cs - Validation: Generic model compiles
- Location:
Phase 3: Authentication Service
-
010: Create IAuthService interface
- Location:
NEW/src/JdeScoping.Api/Services/IAuthService.cs - Methods: AuthenticateAsync, GetUserInfoAsync
- Include CancellationToken parameters
- Validation: Interface compiles
- Location:
-
011: Create LdapAuthService implementation
- Location:
NEW/src/JdeScoping.Api/Services/LdapAuthService.cs - Source:
OLD/WebInterface/Helpers/LDAPHelper.cs - Use System.DirectoryServices.Protocols (NOT System.DirectoryServices)
- Implement failover across multiple server URLs
- Implement group membership verification
- Validation: Service compiles, passes unit tests for mocked scenarios
- Location:
-
012: Create FakeAuthService implementation
- Location:
NEW/src/JdeScoping.Api/Services/FakeAuthService.cs - Accept any credentials, return predefined UserInfo
- Validation: Service compiles, unit tests pass
- Location:
Phase 4: Security Helpers
-
013: Create UserIdentity helper
- Location:
NEW/src/JdeScoping.Api/Security/UserIdentity.cs - Source:
OLD/WebInterface/Security/UserIdentity.cs - Create ClaimsIdentity from UserInfo
- Validation: Helper compiles
- Location:
-
014: Create ClaimsPrincipalExtensions
- Location:
NEW/src/JdeScoping.Api/Security/ClaimsPrincipalExtensions.cs - Method: ToUserInfo() extension for ClaimsPrincipal
- Validation: Extension compiles and works correctly
- Location:
Phase 5: Base Controller
- 015: Create ApiControllerBase
- Location:
NEW/src/JdeScoping.Api/Controllers/ApiControllerBase.cs - Source:
OLD/WebInterface/Controllers/CrudController.cs - Provide CurrentUser and CurrentUserName properties
- Validation: Base controller compiles
- Location:
Phase 6: Auth Controller
- 016: Create AuthController
- Location:
NEW/src/JdeScoping.Api/Controllers/AuthController.cs - Source:
OLD/WebInterface/Controllers/AccountController.cs - Endpoints: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
- Use IAuthService for authentication
- Use HttpContext.SignInAsync/SignOutAsync
- Return JSON (not redirect) for Blazor WASM
- Validation: Controller compiles, endpoints respond correctly
- Location:
Phase 7: Search Controller
- 017: Create SearchController
- Location:
NEW/src/JdeScoping.Api/Controllers/SearchController.cs - Source:
OLD/WebInterface/Controllers/SearchController.cs - Endpoints:
- GET /api/search - user's searches
- GET /api/search/queue - queued searches
- GET /api/search/{id} - single search
- POST /api/search/{id}/copy - copy search
- POST /api/search - create search
- GET /api/search/{id}/results - download results
- Apply [Authorize] at controller level
- Inject IHubContext for SignalR notifications
- Validation: Controller compiles, endpoints respond correctly
- Location:
Phase 8: Lookup Controller
- 018: Create LookupController
- Location:
NEW/src/JdeScoping.Api/Controllers/LookupController.cs - Source:
OLD/WebInterface/Controllers/LookupController.cs - Endpoints:
- GET /api/lookup/items?q= - search items
- GET /api/lookup/profit-centers?q= - search profit centers
- GET /api/lookup/work-centers?q= - search work centers
- GET /api/lookup/operators?q= - search operators
- NO authorization required (public endpoints)
- Validation: Controller compiles, endpoints respond correctly
- Location:
Phase 9: File Controller
-
019: Create ExcelTemplateGenerator helper
- Location:
NEW/src/JdeScoping.Api/Helpers/ExcelTemplateGenerator.cs - Source:
OLD/DataModel/Helpers/ExcelTemplateGenerator.cs - Use ClosedXML (not EPPlus)
- Methods: Generate(data, headers)
- Validation: Helper generates valid Excel files
- Location:
-
020: Create FileController
- Location:
NEW/src/JdeScoping.Api/Controllers/FileController.cs - Source:
OLD/WebInterface/Controllers/FileIOController.cs - Endpoints:
- POST /api/file/work-orders/upload
- POST /api/file/work-orders/template (returns cache key)
- GET /api/file/work-orders/template/{key}
- POST /api/file/part-numbers/upload
- POST /api/file/part-numbers/template
- GET /api/file/part-numbers/template/{key}
- POST /api/file/component-lots/upload
- POST /api/file/component-lots/template
- GET /api/file/component-lots/template/{key}
- POST /api/file/part-operations/upload
- POST /api/file/part-operations/template
- GET /api/file/part-operations/template/{key}
- Use IMemoryCache with 1-minute expiration
- Use ClosedXML for Excel parsing
- NO authorization required (matches legacy)
- Validation: Controller compiles, file upload/download works
- Location:
Phase 10: SignalR Hub
- 021: Create StatusHub
- Location:
NEW/src/JdeScoping.Api/Hubs/StatusHub.cs - Source:
OLD/WebInterface/Hubs/StatusHub.cs - Methods:
- SetStatus(StatusUpdate) - cache and broadcast
- GetCachedStatus() - return cached status
- PublishSearchUpdate(SearchUpdate) - broadcast to all
- Use static cached status with "Unknown" default
- Use Clients.All.SendAsync() pattern
- Validation: Hub compiles, connections work
- Location:
Phase 11: Service Registration
-
022: Create ServiceCollectionExtensions
- Location:
NEW/src/JdeScoping.Api/ServiceCollectionExtensions.cs - Methods:
- AddWebApi(services, configuration) - registers all services
- UseWebApi(app) - configures middleware
- Register IAuthService based on UseFakeAuth setting
- Configure cookie authentication with 401 on unauthorized
- Configure SignalR
- Configure Swagger/OpenAPI
- Validation: Services resolve correctly at runtime
- Location:
-
023: Update Program.cs to use web API services
- Location:
NEW/src/JdeScoping.Host/Program.cs - Add:
builder.Services.AddWebApi(builder.Configuration); - Add:
app.UseWebApi(); - Validation: Application starts without DI errors
- Location:
Phase 12: Configuration Files
-
024: Update appsettings.json with Auth and Ldap sections
- Location:
NEW/src/JdeScoping.Host/appsettings.json - Add Auth section with production defaults
- Add Ldap section with placeholder values
- Validation: Configuration binds correctly
- Location:
-
025: Create appsettings.Development.json
- Location:
NEW/src/JdeScoping.Host/appsettings.Development.json - Set UseFakeAuth = true for development
- Validation: Dev mode uses fake authentication
- Note: File already existed with UseFakeAuth = true
- Location:
Phase 13: Unit Tests
-
026: Create test project
- Location:
NEW/tests/JdeScoping.Api.Tests/JdeScoping.Api.Tests.csproj - Dependencies: xUnit, Shouldly, NSubstitute, Microsoft.AspNetCore.Mvc.Testing
- Validation: Test project builds
- Location:
-
027: Write AuthController tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Controllers/AuthControllerTests.cs - Test: Login with valid credentials returns UserInfo
- Test: Login with invalid credentials returns 401
- Test: Logout clears authentication
- Test: GetCurrentUser returns user when authenticated
- Test: GetCurrentUser returns 401 when not authenticated
- Validation: All tests pass
- Location:
-
028: Write SearchController tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Controllers/SearchControllerTests.cs - Test: GetSearches returns user's searches ordered by date
- Test: CreateSearch saves and publishes to SignalR
- Test: CopySearch resets status and timestamps
- Test: GetResults returns file with correct content type
- Test: Unauthenticated requests return 401
- Validation: All tests pass
- Location:
-
029: Write LookupController tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Controllers/LookupControllerTests.cs - Test: FindItems returns ordered results
- Test: FindProfitCenters returns ordered results
- Test: FindWorkCenters returns ordered results
- Test: FindOperators returns ordered results
- Validation: All tests pass
- Location:
-
030: Write FileController tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Controllers/FileControllerTests.cs - Test: UploadWorkOrders parses Excel correctly
- Test: GenerateTemplate caches and returns key
- Test: DownloadTemplate returns file and removes from cache
- Test: Expired cache key returns 404
- Validation: All tests pass
- Location:
-
031: Write LdapAuthService tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Services/LdapAuthServiceTests.cs - Test: Invalid credentials returns failure
- Test: User not in group returns appropriate error
- Test: All servers unavailable returns connection error
- Note: Use mocks for LDAP connection (integration tests separate)
- Validation: All tests pass
- Location:
-
032: Write FakeAuthService tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Services/FakeAuthServiceTests.cs - Test: Any credentials return success
- Test: UserInfo populated correctly
- Validation: All tests pass
- Location:
-
033: Write StatusHub tests
- Location:
NEW/tests/JdeScoping.Api.Tests/Hubs/StatusHubTests.cs - Test: SetStatus caches and broadcasts
- Test: GetCachedStatus returns cached value
- Test: Initial cached status is "Unknown"
- Validation: All tests pass
- Location:
Phase 14: Integration Tests
-
034: Create integration test project
- Location:
NEW/tests/JdeScoping.Api.IntegrationTests/JdeScoping.Api.IntegrationTests.csproj - Use WebApplicationFactory for testing
- Validation: Test project builds
- Location:
-
035: Write authentication integration tests
- Location:
NEW/tests/JdeScoping.Api.IntegrationTests/AuthenticationTests.cs - Test: Full login/logout flow with cookies
- Test: Protected endpoints return 401 without auth
- Test: Protected endpoints work with auth cookie
- Validation: All tests pass
- Location:
-
036: Write SignalR integration tests
- Location:
NEW/tests/JdeScoping.Api.IntegrationTests/SignalRTests.cs - Test: Client can connect to /hubs/status
- Test: Client receives status updates
- Test: Client can call GetCachedStatus
- Validation: All tests pass
- Location:
Phase 15: Verification
-
037: Run full test suite
- Command:
dotnet test NEW/tests/JdeScoping.Api.Tests/ - Command:
dotnet test NEW/tests/JdeScoping.Api.IntegrationTests/ - Validation: All tests pass (34 unit tests pass)
- Command:
-
038: Verify solution builds
- Command:
dotnet build NEW/JdeScoping.slnx - Validation: No errors or warnings (Host project builds successfully)
- Command:
-
039: Verify application starts
- Command:
dotnet run --project NEW/src/JdeScoping.Host - Validation: Application starts, Swagger UI accessible at /swagger
- Command:
-
040: Verify API endpoints
- Test: /api/auth/login responds
- Test: /api/lookup/* endpoints respond without auth
- Test: /api/search/* endpoints require auth
- Test: /hubs/status SignalR connection works
- Validation: All endpoints functional
-
041: Run OpenSpec validation
- Command:
openspec validate implement-web-api --strict - Validation: No validation errors
- Command:
-
042: Codex MCP review of controller implementations
- Compare controller actions against legacy
- Verify all endpoints match legacy behavior
- Validation: No significant behavioral differences