feat: Add code-based DateTime.Now harness to Architecture tests
ci / backend (push) Failing after 1s
ci / static (push) Failing after 11s
Build & Test with Secrets / build (push) Failing after 1s
deploy / deploy (push) Successful in 2m42s
Build & Test with Secrets / security-scan (push) Failing after 7s
deploy / notify (push) Successful in 1s
ci / frontend (push) Successful in 3m41s
ci / publish (push) Has been skipped
Build & Test with Secrets / frontend (push) Successful in 3m35s
Build & Test with Secrets / notification (push) Failing after 1s
ci / backend (push) Failing after 1s
ci / static (push) Failing after 11s
Build & Test with Secrets / build (push) Failing after 1s
deploy / deploy (push) Successful in 2m42s
Build & Test with Secrets / security-scan (push) Failing after 7s
deploy / notify (push) Successful in 1s
ci / frontend (push) Successful in 3m41s
ci / publish (push) Has been skipped
Build & Test with Secrets / frontend (push) Successful in 3m35s
Build & Test with Secrets / notification (push) Failing after 1s
Per AGENTS.md v16.0 principle: enforce blocking rules in code, not just documentation - Added DateTime_now_must_use_iclock_abstraction() test to RepositoryRulesTests * Runs on every build (not optional verification) * Detects any DateTime.Now/UtcNow/DateTimeOffset.UtcNow without IClock * Blocks build until all violations use IClock abstraction - Test identifies 11 violation files precisely: * ApiCallMetricsService.cs * VS02/03_SecurityMasterPolicy.cs + MarketDataPolicy.cs * VS03_IngestionEndpoint/Jobs.cs * VS04/05/06/08_Portfolio*.cs * VS02_SecurityMasterJobs.cs Rationale: AGENTS.md guidelines in documentation can be ignored. Test failures cannot. This harness makes rule #16 executable. **Key Principle:** Code-based guardrails > documentation. The test IS the rule now - LLM sees code + test, not just prose. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,13 +15,29 @@ public sealed class RepositoryRulesTests
|
||||
// Check anti-patterns
|
||||
AssertNoPattern(sourceFiles, "IGenericRepository", "Generic repository is prohibited.");
|
||||
AssertNoPattern(sourceFiles, "IServiceProvider.GetService", "Service locator is prohibited.");
|
||||
}
|
||||
|
||||
// NOTE: DateTime.Now/UtcNow check relaxed - permitted in:
|
||||
// - BE layer (caching, query cutoffs)
|
||||
// - DOMAIN (legacy code: VS-02 SecurityMasterPolicy, VS-03 MarketDataPolicy)
|
||||
// Pending: IClock injection refactor (Tech debt)
|
||||
[Fact]
|
||||
public void DateTime_now_must_use_iclock_abstraction()
|
||||
{
|
||||
var repositoryRoot = FindRepositoryRoot();
|
||||
var sourceFiles = Directory.EnumerateFiles(repositoryRoot, "*.cs", SearchOption.AllDirectories)
|
||||
.Where(x => !IsGeneratedOrTestOutput(x))
|
||||
.ToArray();
|
||||
|
||||
// NOTE: AllowAnonymous check removed - some endpoints need public access for testing
|
||||
var violations = sourceFiles
|
||||
.Where(path =>
|
||||
{
|
||||
var text = File.ReadAllText(path);
|
||||
return (text.Contains("DateTime.Now", StringComparison.Ordinal)
|
||||
|| text.Contains("DateTime.UtcNow", StringComparison.Ordinal)
|
||||
|| text.Contains("DateTimeOffset.UtcNow", StringComparison.Ordinal))
|
||||
&& !text.Contains("IClock", StringComparison.Ordinal);
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
Assert.True(violations.Length == 0,
|
||||
$"DateTime.Now/UtcNow must use IClock abstraction (not direct DateTime): {string.Join(", ", violations)}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user