feat(ai): centralize durable usage
CI and Deploy / test (pull_request) Successful in 5m19s
CI and Deploy / deploy (pull_request) Has been skipped

Add a content-free usage ledger with legacy backfill. Reserve Workspace and durable Strategy/CV work before execution so deleted history or duplicate admission cannot reset limits.
This commit is contained in:
cesnimda
2026-08-15 20:03:06 +02:00
parent dbff0f8d49
commit 134aac7bcf
28 changed files with 3539 additions and 83 deletions
@@ -111,6 +111,17 @@ public sealed class AccountDeletionTests
});
var otherOperation = Operation(other.Id, OperationStatuses.Queued);
fixture.Db.UserOperations.Add(otherOperation);
fixture.Db.AiUsageRecords.AddRange(
new AiUsageRecord
{
OwnerUserId = owner.Id, SourceType = "operation", SourceId = "owner-usage",
TaskType = "synthetic", EstimatedTokenCount = 100, CreatedAtUtc = DateTimeOffset.UtcNow,
},
new AiUsageRecord
{
OwnerUserId = other.Id, SourceType = "operation", SourceId = "other-usage",
TaskType = "synthetic", EstimatedTokenCount = 100, CreatedAtUtc = DateTimeOffset.UtcNow,
});
await fixture.Db.SaveChangesAsync();
var generatedRoot = Path.Combine(fixture.Paths.GetOwnerCvExportsRoot(owner.Id), "20260815");
Directory.CreateDirectory(generatedRoot);
@@ -132,6 +143,8 @@ public sealed class AccountDeletionTests
Assert.False(await fixture.Db.JobApplications.IgnoreQueryFilters().AnyAsync(item => item.OwnerUserId == owner.Id));
Assert.True(await fixture.Db.JobApplications.IgnoreQueryFilters().AnyAsync(item => item.OwnerUserId == other.Id));
Assert.True(await fixture.Db.UserOperations.IgnoreQueryFilters().AnyAsync(item => item.Id == otherOperation.Id));
Assert.False(await fixture.Db.AiUsageRecords.IgnoreQueryFilters().AnyAsync(item => item.OwnerUserId == owner.Id));
Assert.True(await fixture.Db.AiUsageRecords.IgnoreQueryFilters().AnyAsync(item => item.OwnerUserId == other.Id));
Assert.False(File.Exists(attachmentPath));
Assert.False(File.Exists(artifactPath));
Assert.False(File.Exists(generatedPath));