Skip to content

Commit 711101b

Browse files
committed
Add DI-path test for hosted-service policy backend replacement
1 parent 197256d commit 711101b

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

test/AWS.Bedrock.MAG.UnitTests/Setup/SetupWiringTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,51 @@ public async Task Startup_clears_existing_policy_backends_when_replace_is_set()
288288
Assert.Equal(BedrockGuardrailsPolicyBackend.BackendName, backend);
289289
}
290290

291+
[Fact]
292+
public async Task DI_registration_runs_hosted_service_and_replaces_policy_backends()
293+
{
294+
// Full DI path: register through the public AddBedrockGovernance API and let the host run the
295+
// registered IHostedService, rather than newing up BedrockGovernanceStartup directly. This locks in
296+
// that the toolkit's kernel is fully populated at resolve time (construction-time policy loading, no
297+
// toolkit hosted service), so ClearPolicies runs against a complete PolicyEngine and can't be
298+
// silently re-populated by a later-ordered hosted service.
299+
var kernel = new GovernanceKernel();
300+
kernel.PolicyEngine.LoadYaml(
301+
"""
302+
apiVersion: governance.toolkit/v1
303+
name: baseline
304+
default_action: deny
305+
rules: []
306+
""");
307+
kernel.PolicyEngine.AddExternalBackend(new StubExternalBackend("seeded-external"));
308+
309+
var services = new ServiceCollection();
310+
// Mirrors the toolkit's WithGovernance kernel registration.
311+
services.AddSingleton(kernel);
312+
services.AddBedrockGovernance(o =>
313+
{
314+
o.EnablePolicy = true;
315+
o.EnableAudit = false;
316+
o.EnablePiiSanitization = false;
317+
o.ReplacePolicyBackends = true;
318+
o.Policy.GuardrailId = "gr";
319+
// Deterministic region so the Bedrock client constructs without ambient AWS config.
320+
o.Policy.Region = RegionEndpoint.USWest2;
321+
});
322+
323+
using var provider = services.BuildServiceProvider();
324+
325+
// Run the hosted services exactly as the generic host would at startup.
326+
foreach (var hosted in provider.GetServices<IHostedService>())
327+
{
328+
await hosted.StartAsync(CancellationToken.None);
329+
}
330+
331+
Assert.Empty(kernel.PolicyEngine.ListPolicies());
332+
var backend = Assert.Single(kernel.PolicyEngine.ListExternalBackends());
333+
Assert.Equal(BedrockGuardrailsPolicyBackend.BackendName, backend);
334+
}
335+
291336
// Minimal external backend for seeding the PolicyEngine; never evaluated in these wiring tests.
292337
private sealed class StubExternalBackend : global::AgentGovernance.Policy.IExternalPolicyBackend
293338
{

0 commit comments

Comments
 (0)