fix: harden request validation and profileArn handling for Kiro API#222
fix: harden request validation and profileArn handling for Kiro API#222ranjanjyoti152 wants to merge 2 commits into
Conversation
Addresses multiple validation failures that surfaced as opaque upstream errors when proxying Claude Code / Anthropic and OpenAI requests. Core fixes (shared, applied to both APIs and streaming + non-streaming): - Accept inline "system" role inside the Anthropic messages array and fold it into the system prompt (was a hard 422), preserving order and combining with any top-level system field. - Strip JSON Schema meta keywords ($schema, $id, $anchor, $comment) from tool inputSchema. Claude Code sends "$schema" on every tool, which Kiro/Bedrock rejected as REQUEST_BODY_INVALID. $ref/$defs are preserved. - Guarantee every tool inputSchema root is type:"object" with a properties map, fixing Bedrock "inputSchema.json.type must be one of [object]". Profile ARN robustness: - Add a shared Profile_Resolver (auth manager -> PROFILE_ARN -> empty). - Detect missing profileArn before contacting Kiro and return an actionable HTTP 400 in the correct per-API error format, instead of an opaque upstream 400. - Validate profileArn shape and reject the "..." placeholder with a clear message guiding the user to set a real ARN. New module: kiro/profile_resolver.py New exceptions: MissingProfileArnError, MalformedProfileArnError Tests: comprehensive coverage across both APIs and both streaming modes, including schema sanitization, object-type normalization, inline system folding, resolver rules, and ARN validation.
|
Thanks for the PR! 🎉 Before merge, we need a one-time CLA confirmation. Full CLA text: Please reply once with: You need to write once, all further messages from me can be ignored. |
|
I have read the CLA and I accept its terms
…On Mon, 15 Jun 2026 at 4:56 PM, cla-bot[bot] ***@***.***> wrote:
*cla-bot[bot]* left a comment (jwadow/kiro-gateway#222)
<#222 (comment)>
Thanks for the PR! 🎉
Before merge, we need a one-time CLA confirmation.
It confirms that you have the right to contribute this code and allow the
project to use it.
Full CLA text:
https://github.com/jwadow/kiro-gateway/blob/main/CLA.md
Please reply once with:
I have read the CLA and I accept its terms
You need to write once, all further messages from me can be ignored.
—
Reply to this email directly, view it on GitHub
<#222?email_source=notifications&email_token=AFQQEP66FNOWU6UJJTNQIID477MOXA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINZQG42DGNBWHA42M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-4707434689>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFQQEP7ICI6P7FKNK6K4HWD477MOXAVCNFSNUABGKJSXA33TNF2G64TZHMYTCMJVGQ4DSMRRHA5US43TOVSTWNBWGY2DMMRSGIZTRILWAI>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
|
I have read the CLA and I accept its terms |
|
Thanks for the PR! 🎉 Before merge, we need a one-time CLA confirmation. Full CLA text: Please reply once with: You need to write once, all further messages from me can be ignored. |
|
I have read the CLA and I accept its terms |
|
@jwadow I've posted the CLA acceptance ("I have read the CLA and I accept its terms") but the cla-bot isn't re-checking. Could you re-run the CLA check or add me to the contributors list? Thanks! 🙏 |
Summary
Hardens request validation and
profileArnhandling so several requests thatpreviously failed with opaque upstream errors now work, and any remaining
misconfiguration produces an actionable message instead of Kiro's cryptic
REQUEST_BODY_INVALID.All changes follow the project philosophy: shared core fixes applied to both
the OpenAI and Anthropic surfaces and both streaming and non-streaming
paths, with paranoid test coverage.
What it fixes
These all surfaced as
HTTP 400 Improperly formed request (REQUEST_BODY_INVALID)or hard
422s when proxying Claude Code traffic:Inline
systemrole in the Anthropicmessagesarray — some clients(Claude Code) inline
{"role": "system", ...}instead of using thetop-level
systemfield. This was rejected with a Pydantic422. Now therole is accepted and folded into the system prompt (order preserved,
combined with any top-level
system, excluded from history).$schema(and other JSON Schema meta keywords) in toolinput_schema—Claude Code sends
"$schema"on every tool. Kiro/Bedrock rejects it. Thesanitizer now strips
$schema,$id,$anchor,$commentrecursively(preserving structural
$ref/$defs).Tool schema root type — Bedrock requires every tool
inputSchema.json.typeto be"object"(error:toolConfig.tools.N.toolSpec.inputSchema.json.type must be one of [object]).No-argument / malformed tool schemas are now normalized to a valid object
schema with a
propertiesmap.profileArnhandling — a sharedProfile_Resolver(auth manager →
PROFILE_ARN→ empty) with:opaque upstream 400), and
...documentation placeholder with aclear message telling the user to set a real ARN.
New
kiro/profile_resolver.py— shared resolution + ARN validationMissingProfileArnError,MalformedProfileArnErrorTests
Comprehensive unit + integration coverage across both APIs and both streaming
modes: schema sanitization, object-type normalization, inline-system folding
and ordering, resolver rules, ARN validation, and route-level error responses.
Full suite passes locally.
Note for maintainers
The README states AWS SSO / Builder ID users don't need a
profileArn. Themissing/malformed
profileArnguards here were validated against anEnterprise / IAM Identity Center account where the Kiro runtime does
require it. Happy to gate the strictness (e.g. only error for auth types that
require a profileArn) if you'd prefer — let me know.