Skip to content

[WIP] Plan implementation for backend documentation updates#20

Merged
Chris0Jeky merged 30 commits intomainfrom
copilot/plan-and-implement-backend-docs
Feb 13, 2026
Merged

[WIP] Plan implementation for backend documentation updates#20
Chris0Jeky merged 30 commits intomainfrom
copilot/plan-and-implement-backend-docs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 12, 2026

Backend Activation - Remaining Implementation

Based on the problem statement and reviewing what's been completed, here's the plan to finish the end-to-end implementation:

Completed So Far ✅

  • Domain entities (AutomationProposal, ArchiveItem, ChatSession, ChatMessage, CommandRun, etc.)
  • Repository interfaces and implementations
  • EF Core configurations and migration
  • IUserContext and UserContext for claim-based identity
  • AutomationProposalService, AutomationPolicyEngine, AutomationPlannerService, AutomationExecutorService
  • ArchiveRecoveryService
  • AutomationProposalsController
  • ArchiveController

Wave 2: Missing Backend Surfaces (Remaining)

  • Implement ILlmProvider abstraction
  • Implement LlmChatService with deterministic mock
  • Create LlmChatController with SSE streaming endpoints
  • Implement CommandExecutionService with command allowlist
  • Implement LogQueryService with filtering and correlation
  • Create OpsController for CLI bridge
  • Create LogsController with SSE streaming
  • Add DTOs for all new services

Wave 3: Runtime and Reliability

  • Implement LlmQueueToProposalWorker (IHostedService)
  • Implement ProposalHousekeepingWorker for expiration
  • Add health/readiness endpoints (HealthController)
  • Configure workers in Program.cs with retry/backoff
  • Add telemetry and structured logging

Wave 4: Testing and Integration

  • Add API integration tests for new controllers
  • Add unit tests for chat/ops/log services
  • Add unit tests for workers
  • Verify all endpoints work with authentication
  • Run full test suite and ensure all pass

Wave 5: Documentation

  • Update STATUS.md with completed features
  • Document API endpoints in Swagger
  • Add operational notes

Current Focus: Implementing Wave 2 (chat, ops, logs services and controllers)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 11 commits February 12, 2026 19:47
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
… bugs

Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Updated all new domain entities to use Guid for ID fields to match Entity base class:
- AutomationProposal: BoardId, RequestedByUserId, DecidedByUserId
- AutomationProposalOperation: ProposalId
- ArchiveItem: EntityId, BoardId, ArchivedByUserId, RestoredByUserId
- ChatSession: UserId, BoardId
- ChatMessage: SessionId, ProposalId
- CommandRun: RequestedByUserId
- CommandRunLog: CommandRunId

Also updated repository interfaces and implementations to use Guid parameters.
CorrelationId remains string as it's not an entity reference.

Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
- Created IAutomationProposalService interface with all required operations
- Implemented AutomationProposalService using Result pattern and IUnitOfWork
- Created AutomationProposalDtos with proposal and operation DTOs
- Added comprehensive test suite with 18 passing tests
- All 338 tests in solution pass

Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
- Created IArchiveRecoveryService interface with archive CRUD operations
- Implemented ArchiveRecoveryService with restore logic for boards, columns, and cards
- Added DTOs: CreateArchiveItemDto, ArchiveItemDto, RestoreArchiveItemDto, RestoreResult
- Implemented conflict strategies: Fail, Rename, AppendSuffix
- Added permission checks via IAuthorizationService
- Created audit log entries for archive operations
- Implemented snapshot serialization/deserialization for entity restoration
- Added 26 comprehensive unit tests covering all scenarios
- All tests pass (364 total tests across all projects)

Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
…ion tests

Co-authored-by: Chris0Jeky <59696583+Chris0Jeky@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds backend support for “automation proposals” and “archive recovery” workflows (domain models, persistence, services, controllers, and tests) to enable proposing, approving/rejecting, previewing diffs, and restoring archived entities.

Changes:

  • Introduces new domain entities + EF Core persistence (DbContext, configurations, repositories, migrations) for automation proposals, archive items, chat sessions/messages, and command runs/logs.
  • Adds application services (proposal lifecycle, policy engine, instruction planner, executor, archive recovery) and exposes new REST endpoints via AutomationProposalsController and ArchiveController.
  • Adds extensive unit/integration test coverage for the new services and API endpoints.

Reviewed changes

Copilot reviewed 56 out of 57 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
backend/tests/Taskdeck.Application.Tests/Services/AutomationProposalServiceTests.cs Unit tests for proposal lifecycle operations (create/get/approve/reject/apply/fail/expire/diff/filter).
backend/tests/Taskdeck.Application.Tests/Services/AutomationPolicyEngineTests.cs Unit tests for risk classification and policy/permission validation rules.
backend/tests/Taskdeck.Application.Tests/Services/AutomationPlannerServiceTests.cs Unit tests for parsing instructions into proposal operations.
backend/tests/Taskdeck.Application.Tests/Services/AutomationExecutorServiceTests.cs Unit tests for execute preconditions (idempotency key, approved status, policy/permission failures).
backend/tests/Taskdeck.Application.Tests/Services/ArchiveRecoveryServiceTests.cs Unit tests for archive item creation, listing, and restore scenarios (conflicts, permissions, WIP limits).
backend/tests/Taskdeck.Api.Tests/AutomationProposalsApiTests.cs Integration tests for automation proposal REST endpoints.
backend/tests/Taskdeck.Api.Tests/ArchiveApiTests.cs Integration tests for archive REST endpoints.
backend/src/Taskdeck.Infrastructure/Taskdeck.Infrastructure.csproj Adds package reference related to HTTP context access in Infrastructure.
backend/src/Taskdeck.Infrastructure/Repositories/UnitOfWork.cs Extends UnitOfWork to expose new repositories (automation, archive, chat, command runs).
backend/src/Taskdeck.Infrastructure/Repositories/CommandRunRepository.cs Adds repository queries for command runs (by user/status/template/correlation, with logs).
backend/src/Taskdeck.Infrastructure/Repositories/ChatSessionRepository.cs Adds repository queries for chat sessions (by user/board/status, with messages).
backend/src/Taskdeck.Infrastructure/Repositories/ChatMessageRepository.cs Adds repository queries for chat messages (by session/proposal).
backend/src/Taskdeck.Infrastructure/Repositories/AutomationProposalRepository.cs Adds repository queries for proposals (filters + expired).
backend/src/Taskdeck.Infrastructure/Repositories/ArchiveItemRepository.cs Adds repository queries for archive items (filters + by entity).
backend/src/Taskdeck.Infrastructure/Persistence/TaskdeckDbContext.cs Adds DbSets for new entities.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/CommandRunLogConfiguration.cs EF mapping for command run logs.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/CommandRunConfiguration.cs EF mapping for command runs and logs relationship.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/ChatSessionConfiguration.cs EF mapping for chat sessions and messages relationship.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/ChatMessageConfiguration.cs EF mapping for chat messages.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/AutomationProposalOperationConfiguration.cs EF mapping for proposal operations (including unique idempotency key).
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/AutomationProposalConfiguration.cs EF mapping for proposals and operations relationship.
backend/src/Taskdeck.Infrastructure/Persistence/Configurations/ArchiveItemConfiguration.cs EF mapping for archive items.
backend/src/Taskdeck.Infrastructure/Migrations/TaskdeckDbContextModelSnapshot.cs Updates EF snapshot for new entities.
backend/src/Taskdeck.Infrastructure/Migrations/20260212200649_AddAutomationArchiveChatOpsEntities.cs Adds migration creating new tables and indexes.
backend/src/Taskdeck.Infrastructure/Migrations/20260212200649_AddAutomationArchiveChatOpsEntities.Designer.cs Migration designer output for new entities.
backend/src/Taskdeck.Infrastructure/Identity/UserContext.cs Adds IUserContext implementation reading claims from HttpContext.
backend/src/Taskdeck.Infrastructure/DependencyInjection.cs Registers new repositories in Infrastructure DI.
backend/src/Taskdeck.Domain/Exceptions/DomainException.cs Adds ErrorCodes.InvalidOperation.
backend/src/Taskdeck.Domain/Entities/CommandRunLog.cs New domain entity for command run logs.
backend/src/Taskdeck.Domain/Entities/CommandRun.cs New domain entity for command runs + state transitions.
backend/src/Taskdeck.Domain/Entities/ChatSession.cs New domain entity for chat sessions.
backend/src/Taskdeck.Domain/Entities/ChatMessage.cs New domain entity for chat messages.
backend/src/Taskdeck.Domain/Entities/AutomationProposalOperation.cs New domain entity for proposal operations.
backend/src/Taskdeck.Domain/Entities/AutomationProposal.cs New domain entity for proposals + lifecycle rules.
backend/src/Taskdeck.Domain/Entities/ArchiveItem.cs New domain entity for archive items + restore status transitions.
backend/src/Taskdeck.Application/Services/IAutomationProposalService.cs New service interface for proposal lifecycle APIs.
backend/src/Taskdeck.Application/Services/IAutomationPolicyEngine.cs New service interface for risk/policy/permission validation.
backend/src/Taskdeck.Application/Services/IAutomationPlannerService.cs New service interface for instruction parsing -> proposals.
backend/src/Taskdeck.Application/Services/IAutomationExecutorService.cs New service interface for executing proposals.
backend/src/Taskdeck.Application/Services/IArchiveRecoveryService.cs New service interface for archive creation/listing/restoration.
backend/src/Taskdeck.Application/Services/AutomationProposalService.cs Implements proposal lifecycle operations using UnitOfWork + domain rules.
backend/src/Taskdeck.Application/Services/AutomationPolicyEngine.cs Implements risk classification and policy/permission validation.
backend/src/Taskdeck.Application/Services/AutomationPlannerService.cs Parses simple instruction patterns into proposal operations.
backend/src/Taskdeck.Application/Services/AutomationExecutorService.cs Executes proposal operations via existing Board/Card/Column services with transactions + auditing.
backend/src/Taskdeck.Application/Services/ArchiveRecoveryService.cs Implements archive creation, listing, and restore flows with conflict strategies.
backend/src/Taskdeck.Application/Interfaces/IUserContext.cs Defines claim-based actor identity abstraction and guidance.
backend/src/Taskdeck.Application/Interfaces/IUnitOfWork.cs Extends UnitOfWork interface with new repositories.
backend/src/Taskdeck.Application/Interfaces/ICommandRunRepository.cs Repository interface for command runs.
backend/src/Taskdeck.Application/Interfaces/IChatSessionRepository.cs Repository interface for chat sessions.
backend/src/Taskdeck.Application/Interfaces/IChatMessageRepository.cs Repository interface for chat messages.
backend/src/Taskdeck.Application/Interfaces/IAutomationProposalRepository.cs Repository interface for proposals.
backend/src/Taskdeck.Application/Interfaces/IArchiveItemRepository.cs Repository interface for archive items.
backend/src/Taskdeck.Application/DTOs/AutomationProposalDtos.cs DTOs for proposals, operations, filters, status updates.
backend/src/Taskdeck.Application/DTOs/ArchiveRecoveryDtos.cs DTOs for archive items and restore options/results.
backend/src/Taskdeck.Api/Program.cs Registers new services and adds IUserContext + HttpContext accessor.
backend/src/Taskdeck.Api/Controllers/AutomationProposalsController.cs New automation proposals REST endpoints.
backend/src/Taskdeck.Api/Controllers/ArchiveController.cs New archive listing and restore endpoints.
Files not reviewed (1)
  • backend/src/Taskdeck.Infrastructure/Migrations/20260212200649_AddAutomationArchiveChatOpsEntities.Designer.cs: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +101
string entityType,
Guid entityId,
[FromQuery] Guid restoredByUserId,
[FromBody] RestoreArchiveItemDto dto,
CancellationToken cancellationToken = default)
{
// Find the archive item by entity type and ID
var archiveItems = await _archiveService.GetArchiveItemsAsync(
entityType,
null,
null,
1000,
cancellationToken);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

entityType is used as-is for filtering, but ArchiveItem enforces lowercase values ("board", "column", "card"). Routes/docs suggest values like "Card", which will never match and makes restore brittle/case-sensitive. Normalize entityType (e.g., ToLowerInvariant()) and/or validate against the allowed set before querying.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +50
foreach (var opDto in dto.Operations)
{
var operation = new AutomationProposalOperation(
proposal.Id,
opDto.Sequence,
opDto.ActionType,
opDto.TargetType,
opDto.Parameters,
opDto.IdempotencyKey,
opDto.TargetId,
opDto.ExpectedVersion);

proposal.AddOperation(operation);
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This foreach loop immediately maps its iteration variable to another variable - consider mapping the sequence explicitly using '.Select(...)'.

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +94
if (boardId.HasValue && operation.TargetType.Equals("card", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(operation.TargetId))
{
if (Guid.TryParse(operation.TargetId, out var cardId))
{
var card = await _unitOfWork.Cards.GetByIdAsync(cardId, cancellationToken);
if (card != null && card.BoardId != boardId.Value)
return Result.Failure(ErrorCodes.Forbidden, $"Card {cardId} does not belong to board {boardId}");
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 'if' statements can be combined.

Suggested change
if (boardId.HasValue && operation.TargetType.Equals("card", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(operation.TargetId))
{
if (Guid.TryParse(operation.TargetId, out var cardId))
{
var card = await _unitOfWork.Cards.GetByIdAsync(cardId, cancellationToken);
if (card != null && card.BoardId != boardId.Value)
return Result.Failure(ErrorCodes.Forbidden, $"Card {cardId} does not belong to board {boardId}");
}
if (boardId.HasValue
&& operation.TargetType.Equals("card", StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrEmpty(operation.TargetId)
&& Guid.TryParse(operation.TargetId, out var cardId))
{
var card = await _unitOfWork.Cards.GetByIdAsync(cardId, cancellationToken);
if (card != null && card.BoardId != boardId.Value)
return Result.Failure(ErrorCodes.Forbidden, $"Card {cardId} does not belong to board {boardId}");

Copilot uses AI. Check for mistakes.
try
{
var operations = new List<CreateProposalOperationDto>();
var instructionLower = instruction.ToLowerInvariant();
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to instructionLower is useless, since its value is never read.

Suggested change
var instructionLower = instruction.ToLowerInvariant();

Copilot uses AI. Check for mistakes.
// Arrange
var userId = Guid.NewGuid();
var boardId = Guid.NewGuid();
var columnId = Guid.NewGuid();
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to columnId is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
Add an optional int limit (default 100) to IAutomationProposalRepository.GetByBoardIdAsync to match other query methods and allow limiting the number of returned proposals. The CancellationToken parameter is unchanged.
Introduce GetArchiveItemByEntityAsync to IArchiveRecoveryService to allow fetching an archived item by entity type and ID. The method returns Task<Result<ArchiveItemDto>> and accepts a CancellationToken, enabling lookups by entity attributes for restore or display flows.
Eager-load the Operations navigation property across AutomationProposal repository queries to avoid N+1 issues. Adds an overridden GetByIdAsync that includes Operations, and adds a limit parameter (default 100) to GetByBoardIdAsync with Take(limit) for consistency with other query methods.
Introduce a local limit (default 100 when filter.Limit <= 0) and pass it to repository queries to avoid unbounded result sets. Simplify in-memory filtering by applying each optional filter (Status, BoardId, UserId, RiskLevel) independently rather than only when combined with Status, and cap the final results with Take(limit). Small comment and formatting tweaks in AutomationProposalService.
Add input validation for list parameters (limit range 1..1000) and normalize/validate entityType. Introduce GetArchiveItemByEntityAsync to look up archive items by entity type+ID with validation and not-found handling. Fix authorization handling to propagate errors, and move target-board existence/archived checks into the column/card restore branches so restoring to archived or missing boards is prevented. Improve overall error messages for invalid inputs.
Remove the in-memory _executedOperations dictionary and its contains/add checks. After loading a proposal, return success if proposal.Status == ProposalStatus.Applied to provide idempotent behavior across requests/processes. This avoids relying on transient in-memory state (which could leak memory and fails in multi-process deployments) while preserving existing validation and workflow checks.
Enforce authorization on AutomationProposalsController and inject IAutomationExecutorService and IUserContext. Use a TryGetCurrentUserId helper to populate requested/decidedByUserId for Create/Approve/Reject flows and centralize authentication error responses. Add idempotency (Idempotency-Key) validation and delegate execution to the executor service, then return the updated proposal via GetProposalById. Expand error mapping (including InvalidOperation, AuthenticationFailed, Unauthorized, Forbidden) for consistent HTTP responses.
Enforce authorization on archive endpoints and switch RestoreArchivedItem to use the authenticated user from IUserContext instead of a query param. Validate and normalize entityType (board/column/card), call GetArchiveItemByEntityAsync, and add robust error handling for authentication/authorization/forbidden/invalid operations. Introduces helper methods TryNormalizeEntityType and TryGetCurrentUserId and injects IUserContext into the controller.
Register AutomationPlannerService and AutomationExecutorService against their interfaces (IAutomationPlannerService, IAutomationExecutorService) in Program.cs instead of registering the concrete types directly. This ties the DI container to abstractions, improving testability and allowing easier implementation swaps.
Update AutomationProposalServiceTests to match the updated GetByBoardIdAsync signature by adding the page size argument (100) to the mock setup. This ensures the test mock matches the method's new parameters and returns the expected proposals.
Add a scoped registration in Program.cs that maps IAuthorizationService to the existing AuthorizationService using GetRequiredService. This allows components to depend on the IAuthorizationService interface and reuse the already-registered AuthorizationService implementation.
Update automation API tests to register/authenticate test users and create owned boards before exercising endpoints. Add AuthenticateAsync and CreateOwnedBoardAsync helpers and include Authorization header. Remove decidedByUserId query param from approve/reject calls, send Idempotency-Key header when executing proposals, and update expected errorCode from "Conflict" to "InvalidOperation". Also adjust proposal action payload to target a board (include TargetId) and add System.Net.Http.Headers import.
Add AuthenticateAsync helper to register a test user, obtain a token and set the Authorization header for the test HttpClient. Update archive tests to call AuthenticateAsync before requests and adjust the restore test request path (removed restoredByUserId query). Clean up unused usings and add System.Net.Http.Headers for setting the bearer token.
Move OrderByDescending(p => p.CreatedAt).Take(limit) to after ToListAsync in repository methods (GetByStatusAsync, GetByBoardIdAsync, GetByUserIdAsync, GetByRiskLevelAsync). The queries now materialize results first (preserving Include(p => p.Operations)) and then apply in-memory ordering/limiting to avoid EF translation/client-evaluation issues while keeping the external behavior and limit parameter.
If an explicit DiffPreview exists (non-whitespace) return it; otherwise generate a human-readable preview from the proposal's Operations. Operations are ordered by Sequence and formatted as "{Sequence}. {ActionType} {TargetType[:TargetId]}" joined with newlines. If no operations are present, the method still returns the existing "Diff preview not available" failure. Also tightened the DiffPreview check to IsNullOrWhiteSpace.
Adds a unit test that verifies the restore endpoint returns BadRequest when an invalid entity type is used. The test authenticates, posts a RestoreArchiveItemDto to /api/archive/not-a-type/{id}/restore and asserts a 400 response with errorCode "ValidationError". This ensures the API validates entity type inputs for archive restore operations.
Add two integration tests to AutomationProposalsApiTests:

- ExecuteProposal_WithoutIdempotencyKey_ShouldReturnBadRequest: approves a proposal then attempts to execute it without an idempotency key and asserts a 400 BadRequest with errorCode "ValidationError".
- ApproveProposal_ShouldReturnUnauthorized_WhenNotAuthenticated: clears auth header and asserts approving a proposal returns 401 Unauthorized.

These tests exercise validation and authentication behavior for the automation proposals endpoints.
Add a unit test RestoreArchiveItemAsync_ShouldReturnFailure_WhenAuthorizationCheckFails to ArchiveRecoveryServiceTests. The test sets up an archived item and mocks the authorization service to return a NotFound error for CanWriteBoardAsync, then asserts the service returns a failure with ErrorCode NotFound and an error message indicating the board is missing. This covers the authorization failure path in RestoreArchiveItemAsync.
Copilot AI requested a review from Chris0Jeky February 13, 2026 05:16
Copilot stopped work on behalf of Chris0Jeky due to an error February 13, 2026 05:16
@Chris0Jeky Chris0Jeky marked this pull request as ready for review February 13, 2026 05:16
@Chris0Jeky Chris0Jeky merged commit 0ec94f3 into main Feb 13, 2026
7 of 8 checks passed
@Chris0Jeky Chris0Jeky deleted the copilot/plan-and-implement-backend-docs branch February 13, 2026 05:17
Chris0Jeky added a commit that referenced this pull request Feb 16, 2026
…kend-docs

[WIP] Plan implementation for backend documentation updates
Remaining gap vs full backend docs: chat/ops/log-stream/worker activation is still pending implementation
Chris0Jeky added a commit that referenced this pull request Apr 9, 2026
…805)

Pre-resolve expected merge conflicts across all 10 platform expansion PRs:
- STATUS.md: consolidated wave summary, new CI workflow entries
- IMPLEMENTATION_MASTERPLAN.md: delivery entry #130, next-steps item #20
- TESTING_GUIDE.md: cross-browser, visual regression, mutation, Testcontainers
- decisions/INDEX.md: canonical ADR numbering (0023-0027) resolving
  the 5-way ADR-0023 collision across PRs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants