fix: DEBT-028 - wire ActivateModelHandler, fix data-corrupting activation
Systematic sweep of every *Handler registered in Program.cs (same
method that found DEBT-026/027) found ActivateModelHandler was the
last orphan in Features/ApprovalWorkflow/: no POST /approvals/{id}/activate
endpoint existed, so an Approved proposal could never reach Active -
the entire point of this maker-checker slice.
While wiring it up, found the handler's original call would have
overwritten the checker's approved_by/approval_notes with the
activating SRE's identity (it passed userEmail through
UpdateProposalStatusAsync's approvedBy parameter), and never set
activated_by/activated_at at all despite those columns existing since
migration 0036. Added a dedicated ApprovalWorkflowSql.ActivateProposalAsync
that only touches activation-specific columns, and a regression test
asserting the checker's approval record survives activation unchanged.
Also documents DEBT-029 (discovered, not fixed - genuine cross-cutting
scope): LogAuditEventCommandHandler is never called by any other
slice, so VS-27's audit trail is empty in production regardless of
activity even though its own tests pass. Downgraded AEG-VS-27-01 from
COMPLETED to BLOCKED in the tracker to reflect that honestly.
dotnet build KArtSell.sln -c Release: clean. Not run against a live
database this session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -238,9 +238,12 @@ public class ApprovalWorkflowTests : IAsyncLifetime
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Activate_BySreAfterApproval_TransitionsToActive()
|
||||
public async Task Activate_BySreAfterApproval_TransitionsToActive_AndPreservesApprovalFields()
|
||||
{
|
||||
// Arrange
|
||||
// Arrange: DEBT-028 regression guard — ActivateModelHandler used to call
|
||||
// UpdateProposalStatusAsync with the activating SRE's email as the "approvedBy"
|
||||
// parameter, which overwrote the checker's approved_by/approval_notes, and never set
|
||||
// activated_by/activated_at at all despite those columns existing in the schema.
|
||||
var modelId = await SeedModelAsync();
|
||||
var createHandler = new CreateApprovalProposalHandler(_sql, _clock);
|
||||
var proposalId = await createHandler.Handle(
|
||||
@@ -258,6 +261,11 @@ public class ApprovalWorkflowTests : IAsyncLifetime
|
||||
var proposal = await _sql.GetProposalAsync(proposalId);
|
||||
Assert.NotNull(proposal);
|
||||
Assert.Equal(ApprovalStatus.Active, proposal!.Status);
|
||||
Assert.Equal("sre@company.com", proposal.ActivatedBy);
|
||||
Assert.NotNull(proposal.ActivatedAt);
|
||||
// The checker's approval record must survive activation, not be overwritten by the SRE's identity.
|
||||
Assert.Equal("checker@company.com", proposal.ApprovedBy);
|
||||
Assert.Equal("Approved", proposal.ApprovalNotes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user