Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
179 commits
Select commit Hold shift + click to select a range
1bc5efd
docs: add canonical architecture terminology glossary
cdcavell Aug 22, 2026
6c50793
Merge branch 'main' into issue_work
cdcavell Aug 22, 2026
ac650d3
docs: add visual learning path map
cdcavell Aug 22, 2026
b14c145
Merge branch 'main' into issue_work
cdcavell Aug 22, 2026
dcea06a
docs: add learner self-assessment criteria
cdcavell Aug 22, 2026
9f39fe4
Merge branch 'main' into issue_work
cdcavell Aug 22, 2026
bb9fe3c
docs: add AI governance observability tracing
cdcavell Aug 22, 2026
6784d07
Merge branch 'main' into issue_work
cdcavell Aug 22, 2026
cfd11fd
samples: add policy simulation harness
cdcavell Aug 22, 2026
a3a6668
fix: resolve policy simulation test namespace collision
cdcavell Aug 22, 2026
204fccf
fix: isolate policy simulation test assembly namespace
cdcavell Aug 22, 2026
af60cbf
docs: streamline README with progressive disclosure
cdcavell Aug 23, 2026
5c58c0f
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
0b8bc34
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
90b1966
docs: add permanent technical articles publication surface
cdcavell Aug 23, 2026
4fe452b
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
dbc51d5
docs: publish authorization timing article
cdcavell Aug 23, 2026
62ead45
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
13dc3f3
docs: publish .NET package trust article
cdcavell Aug 23, 2026
3b62f5e
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
3ff6489
docs: improve article discovery and feed metadata
cdcavell Aug 23, 2026
a3cf1f9
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
ffbb451
test: isolate governance observability traces
cdcavell Aug 23, 2026
832585a
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
ec38138
docs: improve RSS channel image metadata
cdcavell Aug 23, 2026
f0466fd
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
3067945
Add repository discussion templates and community guidance
cdcavell Aug 23, 2026
f4b5e82
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
92d6c52
docs: Add social image to root README
cdcavell Aug 23, 2026
2f8f84a
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
88c00f1
Refresh Learning site icon and favicon branding
cdcavell Aug 23, 2026
2c459a4
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
5f97e99
Add GitHub social preview image for Learning
cdcavell Aug 23, 2026
dc90c5a
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
1f033f1
Merge branch 'issue_work' of https://github.com/AsiBackbone/Learning …
cdcavell Aug 23, 2026
f212c83
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
1fdb86b
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
7446bdd
Merge branch 'issue_work' of https://github.com/AsiBackbone/Learning …
cdcavell Aug 23, 2026
8ea7db7
Add role, claims, and capability authorization comparison
cdcavell Aug 23, 2026
5744f2c
Merge branch 'main' into issue_work
cdcavell Aug 23, 2026
2a17dca
Add gateway, mesh, zero-trust, and governed execution comparison
cdcavell Aug 24, 2026
713431d
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
c620b22
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
03ecddf
Add workflow, approval, and governed execution comparison
cdcavell Aug 24, 2026
fb83bb8
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
e798183
Add policy engine and distributed enforcement comparison
cdcavell Aug 24, 2026
08763b1
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
55a8807
Add agent and tool authorization comparison
cdcavell Aug 24, 2026
a4c23a5
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
f3e854b
Add event sourcing and governance provenance comparison
cdcavell Aug 24, 2026
f1ac0fc
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
fadb0f4
Add CQRS and governed execution comparison
cdcavell Aug 24, 2026
2765bdd
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
cb79da9
Merge branch 'main' into issue_work
cdcavell Aug 24, 2026
024010c
feat: generate and validate published site sitemap
cdcavell Aug 25, 2026
951acd1
fix: avoid pre-deployment sitemap link validation failure
cdcavell Aug 25, 2026
15aa80a
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
6281b4a
feat: notify search engines of changed Learning URLs
cdcavell Aug 25, 2026
24d984d
fix: make IndexNow payload serialization AOT-safe
cdcavell Aug 25, 2026
a914e37
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
995b92a
docs: strengthen contextual linking across Learning
cdcavell Aug 25, 2026
3c86bde
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
faf0690
docs: add problem-oriented standalone article backlog
cdcavell Aug 25, 2026
8379bd8
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
c9dc3f8
docs: add governed administrative operation case study
cdcavell Aug 25, 2026
a76be9e
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
33ee8af
docs: add sensitive-data access decision case study
cdcavell Aug 25, 2026
c58b9f0
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
e4959f5
docs: add deployment and infrastructure gate case study
cdcavell Aug 25, 2026
b132a9c
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
8747d6a
fix: repair Mermaid diagrams and simplify top navigation
cdcavell Aug 25, 2026
5f5b791
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
9aab75c
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
281b8f2
docs: add AI-assisted API and tool gateway case study
cdcavell Aug 25, 2026
1d497ce
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
4b89c70
docs: add multi-tenant regional policy overlay case study
cdcavell Aug 25, 2026
b655ded
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
5a1a395
docs: add human acknowledgment workflow case study
cdcavell Aug 25, 2026
ae1644d
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
a0481e1
docs: add capability-scoped background operation case study
cdcavell Aug 25, 2026
0c2ab9c
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
ab7127c
Fix Mermaid sequence diagram syntax in background operation case study
cdcavell Aug 25, 2026
a1b6e41
Fix Mermaid claim-revocation race diagram rendering
cdcavell Aug 25, 2026
e44104f
Fix Mermaid claim-revocation race diagram rendering
cdcavell Aug 25, 2026
afb7600
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
cb98479
Merge branch 'issue_work' of https://github.com/AsiBackbone/Learning …
cdcavell Aug 25, 2026
e4a28e4
docs: add simulated robotics governance case study
cdcavell Aug 25, 2026
627170b
docs: fix robotics case study bookmarks
cdcavell Aug 25, 2026
7e3875d
Merge branch 'main' into issue_work
cdcavell Aug 25, 2026
2c92f88
docs: reconcile roadmap with current repository state
cdcavell Aug 26, 2026
ac0d944
Merge branch 'main' into issue_work
cdcavell Aug 26, 2026
a145cb6
docs: add decision pipeline refactoring lab and sample
cdcavell Aug 26, 2026
a36b4ee
Merge branch 'main' into issue_work
cdcavell Aug 26, 2026
d72d830
docs: publish denied-operation execution invariant article
cdcavell Aug 26, 2026
3d99c12
Merge branch 'main' into issue_work
cdcavell Aug 26, 2026
2aac16c
docs: publish ASP.NET Core authorization decision guide
cdcavell Aug 26, 2026
9ae98d9
Merge branch 'main' into issue_work
cdcavell Aug 26, 2026
761010b
Add competing policy architecture comparison lab
cdcavell Aug 26, 2026
317eea9
Merge branch 'main' into issue_work
cdcavell Aug 26, 2026
116dbe4
feat(learning): add cross-system capability exchange guidance and sample
cdcavell Aug 27, 2026
fafcd95
Merge branch 'main' into issue_work
cdcavell Aug 27, 2026
5836416
feat(learning): add federated governance coordination material
cdcavell Aug 27, 2026
b472eb7
fix(samples): handle nullable federation contribution lookup
cdcavell Aug 27, 2026
6fa2104
Merge branch 'main' into issue_work
cdcavell Aug 27, 2026
6d9f854
feat(learning): add distributed acknowledgment continuation material
cdcavell Aug 27, 2026
770a977
Merge branch 'main' into issue_work
cdcavell Aug 27, 2026
594dab3
feat(learning): add human decision explainability material
cdcavell Aug 27, 2026
d1652b3
Merge branch 'main' into issue_work
cdcavell Aug 27, 2026
9d4ca16
feat(learning): add adaptive risk freshness and drift material
cdcavell Aug 27, 2026
5a9bc77
feat(learning): add adaptive risk freshness and drift material
cdcavell Aug 27, 2026
e2ff2bd
Merge branch 'main' into issue_work
cdcavell Aug 27, 2026
7f1fce0
docs: add durable decision ledger and audit chain learning material
cdcavell Aug 28, 2026
02dad4c
docs: replace retired Amazon QLDB reference
cdcavell Aug 28, 2026
e3dbcbc
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
c7b608a
docs: improve executable sample discoverability
cdcavell Aug 28, 2026
bd6b65d
docs: complete sample navigation and simplify breadcrumbs
cdcavell Aug 28, 2026
94a4ce0
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
3633fa5
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
523ae89
Merge branch 'issue_work' of https://github.com/AsiBackbone/Learning …
cdcavell Aug 28, 2026
b91f58f
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
c8c6db8
docs: publish AI tool proposal authority article
cdcavell Aug 28, 2026
4680783
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
8f075f3
Merge branch 'main' into issue_work
cdcavell Aug 28, 2026
88c091e
docs: publish roles claims and capability selection article
cdcavell Sep 2, 2026
f58c82e
Merge branch 'main' into issue_work
cdcavell Sep 2, 2026
ea1e29b
Merge branch 'main' into issue_work
cdcavell Sep 2, 2026
e0c48b8
Merge branch 'main' into issue_work
cdcavell Sep 2, 2026
4c39e02
docs: correct governance licensing statement
cdcavell Sep 2, 2026
d165c86
Merge branch 'main' into issue_work
cdcavell Sep 2, 2026
f0b42d6
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
7ccbe69
docs: correct lab heading hierarchy
cdcavell Sep 6, 2026
527cf1c
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
512cd0c
docs: restore missing catalog entries
cdcavell Sep 6, 2026
248e008
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
ead0322
docs: standardize pattern classifications
cdcavell Sep 6, 2026
2b22371
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
3c6c1c0
docs: add missing page orientation metadata
cdcavell Sep 6, 2026
be0e3bf
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
5e900e3
Check DOI links, remap tree/main, and validate anchors (#265)
cdcavell Sep 6, 2026
3ede10d
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
fcd9d6b
Give CITATION.cff a DOI and canonicalize Zenodo relations (#266)
cdcavell Sep 6, 2026
4e35a00
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
d11ae3a
fix: trigger docs publishing on the metadata validator and make the f…
cdcavell Sep 6, 2026
32c81e4
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
703bc4f
fix: normalize publication date metadata
cdcavell Sep 6, 2026
5402d1d
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
dfeb22b
fix: clean up DocFX template layout
cdcavell Sep 6, 2026
c63a3d8
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
0ff7a4b
docs: disambiguate fictional ADR lifecycle example
cdcavell Sep 6, 2026
02821a7
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
357921b
docs: normalize repository content conventions
cdcavell Sep 6, 2026
80bceac
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
8e863f4
Merge branch 'main' into issue_work
cdcavell Sep 6, 2026
05d7636
Add standalone article on audit records as evidence
cdcavell Sep 7, 2026
d34f955
Merge branch 'main' into issue_work
cdcavell Sep 7, 2026
da4d790
Merge branch 'issue_work' of https://github.com/AsiBackbone/Learning …
cdcavell Sep 8, 2026
d4e54fe
security: harden Learning repository host controls
cdcavell Sep 8, 2026
6a6d997
Merge branch 'main' into issue_work
cdcavell Sep 8, 2026
4709f8c
Merge branch 'main' into issue_work
cdcavell Sep 10, 2026
ee45931
Merge branch 'main' into issue_work
cdcavell Sep 10, 2026
78d8327
Merge branch 'main' into issue_work
cdcavell Sep 11, 2026
d3af2bc
docs: add OpenSSF Best Practices badge to README
cdcavell Sep 11, 2026
3037b83
Merge branch 'main' into issue_work
cdcavell Sep 11, 2026
4ce7e50
Align Learning workflows with global.json SDK selection
cdcavell Sep 11, 2026
149c652
Merge branch 'main' into issue_work
cdcavell Sep 11, 2026
ef85ece
Align sample validation and dependency suppressions
cdcavell Sep 12, 2026
3088350
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
4a6dbcf
Merge remote-tracking branch 'origin/main' into issue_work
cdcavell Sep 12, 2026
ae92e39
Prepare release 0.15.0
cdcavell Sep 12, 2026
afe6b3c
Merge remote-tracking branch 'origin/issue_work' into issue_work
cdcavell Sep 12, 2026
a0571d3
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
e2a6b95
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
2809030
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
f266ce2
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
506291c
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
b375552
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
f037926
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
f39e1e6
Merge branch 'main' into issue_work
cdcavell Sep 12, 2026
00e502e
Add invariant coverage to foundational samples
cdcavell Sep 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ For code examples:
- Use meaningful names.
- Prefer examples that compile and can be tested.
- Add tests when the lesson depends on behavioral correctness.
- For executable samples, cover every documented outcome and stable reason code, prove negative side-effect invariants, and include relevant invalid-input and cancellation boundaries with descriptive test names.
- Avoid embedding real credentials, secrets, tokens, connection strings, or personally identifiable information.
- Use obviously fictional or placeholder values where examples require identifiers or sensitive-looking data.
- When adding, renaming, or removing an executable sample, update both sample catalogs. Add or revise its repository-facing entry in `samples/README.md`, and update `docs/samples/index.md` with its learning objective, difficulty, key invariant, run command, and canonical README link so the published sample guide remains current.
Expand Down
2 changes: 1 addition & 1 deletion samples/acknowledgment-and-audit-residue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ From the repository root:
dotnet test samples/acknowledgment-and-audit-residue/Tests/AcknowledgmentAndAuditResidue.Tests.csproj
```

The focused xUnit tests make the boundary explicit: acknowledgment can satisfy one governance requirement, but it does not itself grant authorization or execution authority. Re-evaluation still controls the next step, and changed resource state can still block execution.
The focused xUnit tests cover every policy outcome and acknowledgment binding failure, including the expiration boundary and stable reason codes. They also prove that acknowledgment does not grant execution authority, changed resource state can still block execution, and the executable scenarios preserve their correlated audit timelines.

The sample uses deterministic local data and does not call external services.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public void AcknowledgmentDoesNotGrantExecutionAuthority()
GovernanceDecisionOutcome.AcknowledgmentRequired,
initialDecision.Outcome);
Assert.False(initialDecision.CanProceed);
Assert.Equal(
"account.disable.reason-required",
Assert.Single(initialDecision.Reasons).Code);
Assert.Equal(0, executor.InvocationCount);

AcknowledgmentChallenge challenge = CreateChallenge(
Expand Down Expand Up @@ -123,6 +126,215 @@ public void ExpiredAcknowledgmentDoesNotReachExecution()
Assert.Equal(0, executor.InvocationCount);
}

[Fact]
public void RejectedAcknowledgmentIsInvalid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
response with { Accepted = false },
response.OccurredUtc);

Assert.False(validation.IsValid);
Assert.Equal("acknowledgment.rejected", validation.ReasonCode);
}

[Fact]
public void WrongChallengeIdentifierIsInvalid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
response with { ChallengeId = "different-challenge" },
response.OccurredUtc);

Assert.False(validation.IsValid);
Assert.Equal("acknowledgment.challenge-mismatch", validation.ReasonCode);
}

[Fact]
public void WrongActorIsInvalid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
response with { ActorId = "operator-99" },
response.OccurredUtc);

Assert.False(validation.IsValid);
Assert.Equal("acknowledgment.actor-mismatch", validation.ReasonCode);
}

[Fact]
public void WrongAcknowledgmentCodeIsInvalid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
response with { AcknowledgmentCode = "account.disable.wrong-code" },
response.OccurredUtc);

Assert.False(validation.IsValid);
Assert.Equal("acknowledgment.code-mismatch", validation.ReasonCode);
}

[Fact]
public void WrongCorrelationIdentifierIsInvalid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
response with { CorrelationId = "different-correlation" },
response.OccurredUtc);

Assert.False(validation.IsValid);
Assert.Equal("acknowledgment.correlation-mismatch", validation.ReasonCode);
}

[Fact]
public void ResponseAtExpirationBoundaryIsValid()
{
(AcknowledgmentChallenge challenge, AcknowledgmentResponse response) =
CreateValidExchange();
AcknowledgmentResponse boundaryResponse = response with
{
OccurredUtc = challenge.ExpiresUtc
};

AcknowledgmentValidation validation = AcknowledgmentValidator.Validate(
challenge,
boundaryResponse,
boundaryResponse.OccurredUtc);

Assert.True(validation.IsValid);
Assert.Equal("acknowledgment.accepted", validation.ReasonCode);
}

[Fact]
public void NonAdministratorIsDeniedWithStableReasonCode()
{
DisableAccountPolicyContext original = CreateContext();
DisableAccountPolicyContext context = original with
{
Actor = original.Actor with { IsAdministrator = false }
};

GovernanceDecision decision = DisableAccountPolicy.Evaluate(context);

Assert.Equal(GovernanceDecisionOutcome.Denied, decision.Outcome);
Assert.Equal(
"account.disable.not-administrator",
Assert.Single(decision.Reasons).Code);
}

[Fact]
public void CrossTenantRequestIsDeniedWithStableReasonCode()
{
DisableAccountPolicyContext original = CreateContext();
DisableAccountPolicyContext context = original with
{
Account = original.Account with { TenantId = "tenant-b" }
};

GovernanceDecision decision = DisableAccountPolicy.Evaluate(context);

Assert.Equal(GovernanceDecisionOutcome.Denied, decision.Outcome);
Assert.Equal(
"account.disable.cross-tenant",
Assert.Single(decision.Reasons).Code);
}

[Fact]
public void ProtectedAccountRecommendsEscalationWithStableReasonCode()
{
DisableAccountPolicyContext original = CreateContext();
DisableAccountPolicyContext context = original with
{
Account = original.Account with { IsProtected = true }
};

GovernanceDecision decision = DisableAccountPolicy.Evaluate(context);

Assert.Equal(
GovernanceDecisionOutcome.EscalationRecommended,
decision.Outcome);
Assert.Equal(
"account.disable.protected-account",
Assert.Single(decision.Reasons).Code);
}

[Fact]
public void SuppliedReasonAllowsRequestWithoutReasonCodes()
{
DisableAccountPolicyContext original = CreateContext();
DisableAccountPolicyContext context = original with
{
Intent = original.Intent with { Reason = "Security investigation" }
};

GovernanceDecision decision = DisableAccountPolicy.Evaluate(context);

Assert.Equal(GovernanceDecisionOutcome.Allowed, decision.Outcome);
Assert.True(decision.CanProceed);
Assert.Empty(decision.Reasons);
}

[Fact]
public void AuditResidueKeepsLifecycleIdentityExplicit()
{
var residue = new AuditResidue(
Sequence: 2,
EventId: "test-user-100-event-02",
OccurredUtc: _nowUtc,
ActorId: "operator-7",
OperationName: "account.disable",
Outcome: "AcknowledgmentAccepted",
ReasonCodes: ["account.disable.reason-required", "acknowledgment.accepted"],
CorrelationId: "test-user-100",
PolicyVersion: "3.2",
Stage: "acknowledgment-accepted");

Assert.Equal("test-user-100", residue.CorrelationId);
Assert.Equal("3.2", residue.PolicyVersion);
Assert.Equal("acknowledgment-accepted", residue.Stage);
Assert.Equal(2, residue.ReasonCodes.Count);
}

[Fact]
public void ExecutableScenariosPreserveExpectedAuditTimelines()
{
System.Reflection.MethodInfo entryPoint =
Assert.IsAssignableFrom<System.Reflection.MethodInfo>(
typeof(DisableAccountPolicy).Assembly.EntryPoint);

entryPoint.Invoke(null, [Array.Empty<string>()]);
}

private static (AcknowledgmentChallenge Challenge, AcknowledgmentResponse Response)
CreateValidExchange()
{
DisableAccountPolicyContext context = CreateContext();
GovernanceDecision decision = DisableAccountPolicy.Evaluate(context);
AcknowledgmentChallenge challenge = CreateChallenge(
context,
decision,
_nowUtc);

return (
challenge,
CreateAcceptedResponse(challenge, _nowUtc.AddSeconds(1)));
}

private static DisableAccountPolicyContext CreateContext()
{
return new DisableAccountPolicyContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ From the repository root:
dotnet test samples/centralized-error-handling-and-problem-details/Tests/CentralizedErrorHandlingAndProblemDetails.Tests.csproj
```

The focused tests prove these invariants:
The focused tests cover every governance-to-HTTP outcome, invalid and unknown scenarios, safe known and unexpected exception responses, and trace correlation. They prove these invariants:

```text
Denied governance decision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Logging;
Expand All @@ -15,6 +16,23 @@ public sealed class ErrorHandlingIntegrationTests
private static readonly JsonSerializerOptions _jsonOptions =
new(JsonSerializerDefaults.Web);

[Fact]
public async Task Allowed_governance_decision_returns_no_content_without_exception_handler_log()
{
await using TestApplication application =
await TestApplication.StartAsync(TestContext.Current.CancellationToken);

HttpResponseMessage response = await application.Client.GetAsync(
"/governance/allowed",
TestContext.Current.CancellationToken);

Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
Assert.Empty(await response.Content.ReadAsByteArrayAsync(TestContext.Current.CancellationToken));
Assert.DoesNotContain(
application.LogProvider.Entries,
entry => entry.CategoryName == typeof(ApplicationExceptionHandler).FullName);
}

[Fact]
public async Task Denied_governance_decision_is_explicit_403_without_exception_handler_log()
{
Expand Down Expand Up @@ -65,6 +83,88 @@ await client.GetAsync(
typeof(ApplicationExceptionHandler).FullName);
}

[Fact]
public async Task Acknowledgment_required_decision_maps_to_explicit_409_problem()
{
await using TestApplication application =
await TestApplication.StartAsync(TestContext.Current.CancellationToken);

HttpResponseMessage response = await application.Client.GetAsync(
"/governance/acknowledgment-required",
TestContext.Current.CancellationToken);
ProblemDetails problem = await ReadProblemAsync(
response,
TestContext.Current.CancellationToken);

Assert.Equal(HttpStatusCode.Conflict, response.StatusCode);
Assert.Equal("Acknowledgment Required", problem.Title);
Assert.Equal("/problems/acknowledgment-required", problem.Type);
Assert.Equal("/governance/acknowledgment-required", problem.Instance);
Assert.Equal(
"governance.acknowledgment-required",
GetExtensionString(problem, "code"));
}

[Fact]
public async Task Escalation_recommended_decision_maps_to_distinct_409_problem()
{
await using TestApplication application =
await TestApplication.StartAsync(TestContext.Current.CancellationToken);

HttpResponseMessage response = await application.Client.GetAsync(
"/governance/escalation-recommended",
TestContext.Current.CancellationToken);
ProblemDetails problem = await ReadProblemAsync(
response,
TestContext.Current.CancellationToken);

Assert.Equal(HttpStatusCode.Conflict, response.StatusCode);
Assert.Equal("Escalation Recommended", problem.Title);
Assert.Equal("/problems/escalation-recommended", problem.Type);
Assert.Equal(
"governance.escalation-recommended",
GetExtensionString(problem, "code"));
}

[Fact]
public async Task Unknown_governance_scenario_remains_a_not_found_problem()
{
await using TestApplication application =
await TestApplication.StartAsync(TestContext.Current.CancellationToken);

HttpResponseMessage response = await application.Client.GetAsync(
"/governance/not-a-scenario",
TestContext.Current.CancellationToken);
ProblemDetails problem = await ReadProblemAsync(
response,
TestContext.Current.CancellationToken);

Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
Assert.DoesNotContain(
application.LogProvider.Entries,
entry => entry.CategoryName == typeof(ApplicationExceptionHandler).FullName);
}

[Fact]
public void Empty_governance_scenario_is_rejected_as_invalid_input()
{
Assert.Throws<ArgumentException>(
() => GovernanceDecision.TryFromScenario(" ", out _));
}

[Fact]
public void Governance_scenario_matching_is_case_insensitive()
{
bool found = GovernanceDecision.TryFromScenario(
"DeNiEd",
out GovernanceDecision decision);

Assert.True(found);
Assert.Equal(GovernanceDecisionOutcome.Denied, decision.Outcome);
Assert.Equal("governance.denied", decision.Code);
}

[Fact]
public async Task Unexpected_exception_becomes_safe_500_without_sensitive_detail()
{
Expand Down
2 changes: 1 addition & 1 deletion samples/decision-before-execution/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ From the repository root:
dotnet test samples/decision-before-execution/Tests/DecisionBeforeExecution.Tests.csproj
```

The focused xUnit tests assert that denied, deferred, and acknowledgment-required decisions never invoke the executor. A positive-control test confirms that an allowed decision crosses the execution boundary exactly once.
The focused xUnit tests assert every outcome and stable reason code. Denied, deferred, acknowledgment-required, and escalation-recommended decisions never invoke the executor; an allowed decision crosses the boundary exactly once, and cancellation prevents that execution before its side effect is recorded.

The sample evaluates five deterministic scenarios:

Expand Down
Loading
Loading