fix(bedrock): pass bedrock-runtime conformance; real InvokeGuardrailChecks

Merged
VI
11h ago
+1602-230

Summary

Part of restoring true 100% Smithy conformance: main's CI probe passes 256,922/257,391 variants, but the check only fails a service that drops more than 100 variants below its recorded baseline, so these failures were hidden. This PR brings bedrock-runtime to 471/471.

  • InvokeGuardrailChecks: the handler and route existed but the op was missing from supported_actions(), so the probe skipped it (0/22). It now enforces every required field, list limit and enum in the model; roles are lowercase user/assistant/system, each content block needs exactly one non-null member, repeated categories are reported once, and match offsets count characters.
  • Shared PII detector with ApplyGuardrail, so both APIs agree: international phone formats (SSN- and card-shaped digit runs are not phones), 13-19 digit card numbers in any grouping with a Luhn check, plus MAC address, card expiry, IBAN, UK NI, Canadian SIN, VIN and US ITIN. Context-dependent types (names, addresses) report nothing rather than guess.
  • Request metadata: InvokeModel / InvokeModelWithResponseStream reject an X-Amzn-Bedrock-Request-Metadata header over 8500 characters or that is not a JSON map satisfying the RequestMetadata constraints (1..16 entries, key/value length and pattern); Converse / ConverseStream validate their requestMetadata map the same way. Valid metadata is recorded on each invocation.
  • Introspection: GET /_fakecloud/bedrock/invocations entries carry requestMetadata; added to all seven SDKs (Rust, Go, TypeScript, Python, Java, PHP, .NET) and the Bedrock docs page.

bedrock itself stays at 4029/4044: its remaining 15 failures are all negative_too_short_<label> variants where the probe sends an empty path label, which no SDK can send. That is a probe bug fixed globally in a separate PR. The baseline is re-recorded for every service at once in a final PR.

Test plan

  • Unit: guardrail checks (all check types, offsets, dedupe, every model constraint, null union members), PII cases for both APIs (international phones, SSN/card shapes not phones, Amex / 13-digit Visa / Luhn-invalid), request metadata limits and constraints on all four invoke paths.
  • Conformance --test bedrock (40), new InvokeGuardrailChecks test over raw HTTP (the pinned SDK lacks the op).
  • E2E bedrock (53): guardrail checks, validation, request metadata recorded and bounded; bedrock_persistence.
  • SDK type tests in PHP and Python.
  • Probe: bedrock-runtime 11/11 ops, 471/471 variants.

Summary by cubic

Fixes bedrock-runtime conformance to 471/471 by implementing InvokeGuardrailChecks for real and validating request metadata on all invoke paths.

InvokeGuardrailChecks

  • The op was routed but missing from supported_actions(), so the conformance probe skipped it (0/22). It now enforces every required field, list limit, and enum from the model.
  • Shares one PII detector with ApplyGuardrail: international phone formats, 13-19 digit Luhn-checked card numbers, and more pattern-only types; SSN-shaped and card-shaped digit runs are no longer reported as phones.

Request metadata

  • InvokeModel/InvokeModelWithResponseStream reject an X-Amzn-Bedrock-Request-Metadata header over 8500 characters or that violates the RequestMetadata constraints; Converse/ConverseStream validate their requestMetadata map the same way.
  • Valid metadata is recorded on each invocation and exposed as requestMetadata in GET /_fakecloud/bedrock/invocations across all seven SDKs and the docs page.