Skip to content

fix: harden request validation and profileArn handling for Kiro API#222

Open
ranjanjyoti152 wants to merge 2 commits into
jwadow:mainfrom
ranjanjyoti152:fix/request-validation-and-config-robustness
Open

fix: harden request validation and profileArn handling for Kiro API#222
ranjanjyoti152 wants to merge 2 commits into
jwadow:mainfrom
ranjanjyoti152:fix/request-validation-and-config-robustness

Conversation

@ranjanjyoti152

Copy link
Copy Markdown

Summary

Hardens request validation and profileArn handling so several requests that
previously 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:

  1. Inline system role in the Anthropic messages array — some clients
    (Claude Code) inline {"role": "system", ...} instead of using the
    top-level system field. This was rejected with a Pydantic 422. Now the
    role is accepted and folded into the system prompt (order preserved,
    combined with any top-level system, excluded from history).

  2. $schema (and other JSON Schema meta keywords) in tool input_schema
    Claude Code sends "$schema" on every tool. Kiro/Bedrock rejects it. The
    sanitizer now strips $schema, $id, $anchor, $comment recursively
    (preserving structural $ref/$defs).

  3. Tool schema root type — Bedrock requires every tool
    inputSchema.json.type to 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 properties map.

  4. profileArn handling — a shared Profile_Resolver
    (auth manager → PROFILE_ARN → empty) with:

    • early, actionable error when no profileArn can be resolved (instead of an
      opaque upstream 400), and
    • format validation that rejects the ... documentation placeholder with a
      clear message telling the user to set a real ARN.

New

  • kiro/profile_resolver.py — shared resolution + ARN validation
  • Exceptions: MissingProfileArnError, MalformedProfileArnError

Tests

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. The
missing/malformed profileArn guards here were validated against an
Enterprise / 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.

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.
@cla-bot

cla-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

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.

@ranjanjyoti152

ranjanjyoti152 commented Jun 15, 2026 via email

Copy link
Copy Markdown
Author

@ranjanjyoti152

Copy link
Copy Markdown
Author

I have read the CLA and I accept its terms

@cla-bot

cla-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

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.

@ranjanjyoti152

Copy link
Copy Markdown
Author

I have read the CLA and I accept its terms

@ranjanjyoti152

Copy link
Copy Markdown
Author

@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! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant