Skip to content

feat: added WebhookOperation mixin to all config mutation operations and experimentation#899

Open
sauraww wants to merge 1 commit intomainfrom
feat/webhook-smithy
Open

feat: added WebhookOperation mixin to all config mutation operations and experimentation#899
sauraww wants to merge 1 commit intomainfrom
feat/webhook-smithy

Conversation

@sauraww
Copy link
Collaborator

@sauraww sauraww commented Mar 2, 2026

Problem

Without WebhookFailed , a webhook failure either went silent (200) or was incorrectly treated as a full failure (500), the notification wasn't sent through which made it inconsistent with the api behaviour.

Solution

In the generated SDK code (Python, TypeScript, etc.), WebhookFailed becomes a typed error that clients can catch

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced WebhookFailed error handling across all operations, signaling when operations succeed but webhook notifications fail.
    • Extended 20+ API operations to recognize HTTP 512 responses indicating webhook delivery failures.

@sauraww sauraww requested a review from a team as a code owner March 2, 2026 06:35
@semanticdiff-com
Copy link

semanticdiff-com bot commented Mar 2, 2026

Review changes with  SemanticDiff

Changed Files
File Status
  clients/python/sdk/superposition_sdk/models.py  10% smaller
  clients/haskell/sdk/Io/Superposition/Command/BulkOperation.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/ConcludeExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/CreateContext.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/CreateDefaultConfig.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/CreateDimension.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/CreateExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/DeleteContext.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/DeleteDefaultConfig.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/DeleteDimension.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/DiscardExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/GetContextFromCondition.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/MoveContext.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/PauseExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/RampExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/ResumeExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/UpdateDefaultConfig.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/UpdateDimension.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/UpdateOverride.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/UpdateOverridesExperiment.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Command/WeightRecompute.hs Unsupported file format
  clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs Unsupported file format
  clients/haskell/sdk/SuperpositionSDK.cabal Unsupported file format
  clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionAsyncClient.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionClient.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/BulkOperation.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/ConcludeExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateContext.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateDefaultConfig.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateDimension.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteContext.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteDefaultConfig.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteDimension.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/DiscardExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/GetContextFromCondition.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/MoveContext.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/PauseExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/RampExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/ResumeExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateDefaultConfig.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateDimension.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateOverride.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateOverridesExperiment.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/WebhookFailed.java  0% smaller
  clients/java/sdk/src/main/java/io/juspay/superposition/model/WeightRecompute.java  0% smaller
  clients/javascript/sdk/src/commands/BulkOperationCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/ConcludeExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/CreateContextCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/CreateDefaultConfigCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/CreateDimensionCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/CreateExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/DeleteContextCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/DeleteDefaultConfigCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/DeleteDimensionCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/DiscardExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/GetContextFromConditionCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/MoveContextCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/PauseExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/RampExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/ResumeExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/UpdateDefaultConfigCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/UpdateDimensionCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/UpdateOverrideCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/UpdateOverridesExperimentCommand.ts  0% smaller
  clients/javascript/sdk/src/commands/WeightRecomputeCommand.ts  0% smaller
  clients/javascript/sdk/src/models/models_0.ts  0% smaller
  clients/javascript/sdk/src/protocols/Aws_restJson1.ts  0% smaller
  clients/python/sdk/superposition_sdk/_private/schemas.py  0% smaller
  clients/python/sdk/superposition_sdk/deserialize.py  0% smaller
  crates/superposition_sdk/src/error_meta.rs  0% smaller
  crates/superposition_sdk/src/operation/bulk_operation.rs  0% smaller
  crates/superposition_sdk/src/operation/conclude_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/create_context.rs  0% smaller
  crates/superposition_sdk/src/operation/create_default_config.rs  0% smaller
  crates/superposition_sdk/src/operation/create_dimension.rs  0% smaller
  crates/superposition_sdk/src/operation/create_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/delete_context.rs  0% smaller
  crates/superposition_sdk/src/operation/delete_default_config.rs  0% smaller
  crates/superposition_sdk/src/operation/delete_dimension.rs  0% smaller
  crates/superposition_sdk/src/operation/discard_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/get_context_from_condition.rs  0% smaller
  crates/superposition_sdk/src/operation/move_context.rs  0% smaller
  crates/superposition_sdk/src/operation/pause_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/ramp_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/resume_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/update_default_config.rs  0% smaller
  crates/superposition_sdk/src/operation/update_dimension.rs  0% smaller
  crates/superposition_sdk/src/operation/update_override.rs  0% smaller
  crates/superposition_sdk/src/operation/update_overrides_experiment.rs  0% smaller
  crates/superposition_sdk/src/operation/weight_recompute.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_bulk_operation.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_conclude_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_create_context.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_create_default_config.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_create_dimension.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_create_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_delete_context.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_delete_default_config.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_delete_dimension.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_discard_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_get_context_from_condition.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_move_context.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_pause_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_ramp_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_resume_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_update_default_config.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_update_dimension.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_update_override.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_update_overrides_experiment.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_webhook_failed.rs  0% smaller
  crates/superposition_sdk/src/protocol_serde/shape_weight_recompute.rs  0% smaller
  crates/superposition_sdk/src/types/error.rs  0% smaller
  crates/superposition_sdk/src/types/error/_webhook_failed.rs  0% smaller
  crates/superposition_sdk/src/types/error/builders.rs  0% smaller
  docs/docs/api/Superposition.openapi.json  0% smaller
  docs/docs/api/bulk-operation.api.mdx Unsupported file format
  docs/docs/api/conclude-experiment.api.mdx Unsupported file format
  docs/docs/api/create-context.api.mdx Unsupported file format
  docs/docs/api/create-default-config.api.mdx Unsupported file format
  docs/docs/api/create-dimension.api.mdx Unsupported file format
  docs/docs/api/create-experiment.api.mdx Unsupported file format
  docs/docs/api/delete-context.api.mdx Unsupported file format
  docs/docs/api/delete-default-config.api.mdx Unsupported file format
  docs/docs/api/delete-dimension.api.mdx Unsupported file format
  docs/docs/api/discard-experiment.api.mdx Unsupported file format
  docs/docs/api/get-context-from-condition.api.mdx Unsupported file format
  docs/docs/api/move-context.api.mdx Unsupported file format
  docs/docs/api/pause-experiment.api.mdx Unsupported file format
  docs/docs/api/ramp-experiment.api.mdx Unsupported file format
  docs/docs/api/resume-experiment.api.mdx Unsupported file format
  docs/docs/api/update-default-config.api.mdx Unsupported file format
  docs/docs/api/update-dimension.api.mdx Unsupported file format
  docs/docs/api/update-override.api.mdx Unsupported file format
  docs/docs/api/update-overrides-experiment.api.mdx Unsupported file format
  docs/docs/api/weight-recompute.api.mdx Unsupported file format
  smithy/models/context.smithy Unsupported file format
  smithy/models/default-config.smithy Unsupported file format
  smithy/models/dimension.smithy Unsupported file format
  smithy/models/experiments.smithy Unsupported file format
  smithy/models/main.smithy Unsupported file format
  smithy/patches/python.patch Unsupported file format

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds WebhookFailed as a new HTTP 512 error response across all SDK clients and API specifications. When an operation succeeds but webhook notification fails, this error type is returned. Implementation includes error variant definitions, serialization/deserialization logic, protocol handlers, and documentation updates.

Changes

Cohort / File(s) Summary
Haskell SDK Operation Commands
clients/haskell/sdk/Io/Superposition/Command/*.hs
Added WebhookFailed as new error variant to all operation error types (BulkOperation, ConcludeExperiment, CreateContext, CreateDefaultConfig, CreateDimension, CreateExperiment, DeleteContext, DeleteDefaultConfig, DeleteDimension, DiscardExperiment, GetContextFromCondition, MoveContext, PauseExperiment, RampExperiment, ResumeExperiment, UpdateDefaultConfig, UpdateDimension, UpdateOverride, UpdateOverridesExperiment, WeightRecompute). Each file imports WebhookFailed model and extends getErrorParser to recognize WebhookFailed status.
Haskell SDK Model & Build
clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs, clients/haskell/sdk/SuperpositionSDK.cabal
New WebhookFailed model with JSON serialization (ToJSON/FromJSON returning empty object), builder pattern support, and HTTP 512 status mapping. Exposed as public module in cabal file.
Java SDK Client Documentation
clients/java/sdk/src/main/java/io/juspay/superposition/client/*.java
Updated Javadoc annotations in SuperpositionAsyncClient and SuperpositionClient to document WebhookFailed as possible exception for API operations.
Java SDK Model & Error Registry
clients/java/sdk/src/main/java/io/juspay/superposition/model/*.java
New WebhookFailed Smithy-generated exception class extending ModeledException with builder pattern. TypeRegistry registrations added to all operation models (BulkOperation, ConcludeExperiment, CreateContext, CreateDefaultConfig, CreateDimension, CreateExperiment, DeleteContext, DeleteDefaultConfig, DeleteDimension, DiscardExperiment, GetContextFromCondition, MoveContext, PauseExperiment, RampExperiment, ResumeExperiment, UpdateDefaultConfig, UpdateDimension, UpdateOverride, UpdateOverridesExperiment, WeightRecompute) to map WebhookFailed errors.
JavaScript SDK Commands & Models
clients/javascript/sdk/src/commands/*Command.ts, clients/javascript/sdk/src/models/models_0.ts, clients/javascript/sdk/src/protocols/Aws_restJson1.ts
Added @throws WebhookFailed documentation to all command JSDoc blocks. New WebhookFailed exception class extending __BaseException with "server" fault designation. Protocol deserializer updated with de_WebhookFailedRes handler.
Python SDK Schemas & Models
clients/python/sdk/superposition_sdk/schemas.py, clients/python/sdk/superposition_sdk/models.py, clients/python/sdk/superposition_sdk/deserialize.py
New WEBHOOK_FAILED schema with server error and HTTP 512 trait. WebhookFailed dataclass (ApiError with code "WebhookFailed", fault "server"). Error registries updated for all operations to include WebhookFailed mapping. Deserialization handler _deserialize_error_webhook_failed added.
Rust SDK Error Types & Protocol Serialization
crates/superposition_sdk/src/error_meta.rs, crates/superposition_sdk/src/operation/*.rs
New WebhookFailed variant added to error enums in error_meta.rs and all operation modules. Updated error trait implementations (Display, Error::source, ProvideErrorMetadata) for all operations. Added is_webhook_failed() helper methods. Protocol serialization handlers (shape_*.rs) updated with error code matching and de_webhook_failed_json_err deserialization.
Rust SDK Types & Builders
crates/superposition_sdk/src/types/error/, crates/superposition_sdk/src/protocol_serde/shape_webhook_failed.rs
New WebhookFailed error type with message field, ErrorMetadata, Display/Error trait implementations. WebhookFailedBuilder with fluent setters. JSON deserializer handles Message field parsing. Module declaration added to protocol_serde.
Smithy API Definitions
smithy/models/main.smithy, smithy/models/context.smithy, smithy/models/default-config.smithy, smithy/models/dimension.smithy, smithy/models/experiments.smithy
New WebhookFailed error shape with HTTP 512 status and server fault designation. New WebhookOperation mixin trait that declares WebhookFailed error. WebhookOperation applied to all context, default-config, dimension, and experiment operations.
API Documentation & OpenAPI
docs/docs/api/*.api.mdx, docs/docs/api/Superposition.openapi.json
Added 512 WebhookFailed response entries to all endpoint documentation. OpenAPI spec blobs updated to reflect new response code. StatusCodes sections expanded with "512": {"description": "WebhookFailed 512 response"} entries.
Python Packaging
smithy/patches/python.patch
pyproject.toml switched to dynamic versioning; minor trailing comma additions in generated model effective_auth_schemes.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Server
    participant WebhookService
    participant Response

    Client->>Server: Execute Operation (e.g., CreateContext)
    activate Server
    Server->>Server: Process Operation
    Server->>Server: Operation Succeeds
    Server->>WebhookService: Send Webhook Notification
    activate WebhookService
    WebhookService->>WebhookService: Process Webhook
    WebhookService-->>Server: Webhook Fails
    deactivate WebhookService
    Server->>Response: Build Response
    Response->>Response: HTTP 512 WebhookFailed
    deactivate Server
    Server-->>Client: 512 Response + Success Result
    Client->>Client: Receive WebhookFailed Error
    Client->>Client: Inspect Error Type
    alt Is WebhookFailed
        Client->>Client: Handle Partial Success<br/>(Operation succeeded,<br/>webhook notification failed)
    else Other Error
        Client->>Client: Handle Standard Error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • juspay/superposition#877: Introduces ConfigChanged webhook calls that produce 512 webhook-failure responses—the server-side implementation corresponding to these SDK-level WebhookFailed error handling updates.

Suggested labels

enhancement, P1

Suggested reviewers

  • Datron
  • ayushjain17

Poem

🐰 A webhook failure arrives, status 512 in sight,
Operation succeeded, but notification took flight,
SDKs awaken to handle this plight,
Haskell, Java, Python, all burning bright! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding WebhookOperation mixin to config mutation and experimentation operations, which is the primary feature introduced across the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 86.32% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/webhook-smithy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionClient.java (1)

227-352: Clarify WebhookFailed meaning directly in the @throws lines.

At Line 232 and repeated additions, consider adding a short qualifier that this indicates operation success with webhook notification failure to avoid clients treating it as a full mutation failure.

Suggested doc tweak pattern
- * `@throws` WebhookFailed
+ * `@throws` WebhookFailed if the operation succeeds but webhook notification fails.

Also applies to: 493-557, 673-769, 1323-1447, 1503-1650, 1765-1783

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionClient.java`
around lines 227 - 352, Update the Javadoc `@throws` entries for WebhookFailed in
the affected methods (e.g., bulkOperation(BulkOperationInput),
concludeExperiment(ConcludeExperimentInput), createContext(CreateContextInput),
createDefaultConfig(CreateDefaultConfigInput),
createDimension(CreateDimensionInput), createExperiment(CreateExperimentInput)
and other listed ranges) to explicitly state that WebhookFailed indicates the
server-side operation completed but delivery of the webhook notification failed
(i.e., operation succeeded but webhook notification failed), so clients do not
treat it as a full mutation failure; apply the same short qualifier to every
`@throws` WebhookFailed line in the indicated sections.
docs/docs/api/move-context.api.mdx (1)

8-8: Consider suppressing secret-scan noise for generated api frontmatter blobs.

If this encoded field is generated and expected, adding a targeted allowlist rule for this docs path can reduce recurring false-positive leak alerts in CI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/move-context.api.mdx` at line 8, The encoded api frontmatter
blob in move-context.api.mdx is a generated/expected artifact causing
secret-scan false positives; add a targeted allowlist rule in the secret-scan
config (allowlist/exceptions) that whitelists this docs path and/or frontmatter
key "api" for generated blobs, and document the exception with a short
rationale; ensure the rule specifically targets the file pattern
docs/docs/api/*.mdx and the frontmatter key "api" to avoid broad suppression.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs`:
- Line 55: The reference to Network.HTTP.Types.status512 in WebhookFailed.hs
breaks compilation because status512 isn't exported; replace the usage of
expectedStatus with a custom status created via Network.HTTP.Types.mkStatus
(e.g., mkStatus 512 "Webhook Failed") so the module defines expectedStatus using
mkStatus instead of the non-existent status512; keep OverloadedStrings enabled
so the reason phrase literal is coerced correctly.

In `@clients/python/sdk/superposition_sdk/models.py`:
- Around line 679-680: The problem is missing comma separators between adjacent
ShapeID entries inside effective_auth_schemes lists which causes a SyntaxError;
locate every occurrence of the variable/attribute named effective_auth_schemes
in models.py (e.g., the lists containing ShapeID("smithy.api#httpBasicAuth") and
ShapeID("smithy.api#httpBearerAuth")) and add a comma between each ShapeID(...)
element so each list item is properly separated; apply this fix to all reported
locations (around the blocks containing those ShapeID entries near the noted
occurrences) and run an import/syntax check to verify the module parses.

In `@docs/docs/api/bulk-operation.api.mdx`:
- Line 65: The 512 "WebhookFailed" response currently has only a description—add
an explicit response body schema under the 512 entry (e.g.,
"content":{"application/json":{"schema":{...}}}) so API consumers know the
payload; reuse or reference the existing "BulkOperationResponseContent" schema
used for the 200 response (the object titled BulkOperationResponseContent /
ContextActionOut) so the 512 returns the same successful-operation result shape
as documented for other command responses.

In `@docs/docs/api/create-dimension.api.mdx`:
- Line 65: The 512 WebhookFailed entry under the responses object in
CreateDimension response currently only has a description; update the
responses["512"] entry (in the same responses object that contains "200" and
"500") to explicitly specify the response payload: either add a content section
with "application/json" and the correct schema that matches the SDK's
WebhookFailed body (e.g., properties like message, webhook_id, details as
appropriate) or explicitly document an empty body by setting content to an empty
object; ensure the symbol to change is the responses["512"] block so the API
contract is unambiguous for client generators.

In `@docs/docs/api/move-context.api.mdx`:
- Line 65: The 512 response currently only has a description; add a content
schema for the 512 WebhookFailed response mirroring other error responses (e.g.,
like the 500 InternalServerError). Update the responses block for MoveContext so
512 includes application/json content with a schema object (type: "object") and
a properties map containing at least "message" (type: "string") and a title such
as "WebhookFailedResponseContent" so clients can see the exact payload shape;
modify the same responses object where "200", "404", and "500" are defined.

In `@docs/docs/api/Superposition.openapi.json`:
- Around line 697-699: Several "512" response objects (e.g., the response block
that currently has only "description": "WebhookFailed 512 response") are missing
a typed content schema; add a content entry to each 512 response that uses
"application/json" with schema: { "$ref":
"#/components/schemas/WebhookFailedResponseContent" } and then create the
components.schemas.WebhookFailedResponseContent definition (include fields
matching the WebhookFailed error model such as an error code, message, optional
details/metadata and any id/timestamp used elsewhere) so SDKs can generate typed
WebhookFailed exceptions; update every 512 block referenced (all occurrences of
the "WebhookFailed 512 response") to reference this new schema name.
- Around line 697-699: The OpenAPI response entry using the non-standard status
key "512" (description "WebhookFailed 512 response") must be changed to a
standard HTTP status code (e.g., replace "512" with "500" or "503" depending on
whether it's a transient server error) and update the response description
accordingly; also add or update a response body schema for the "WebhookFailed"
response to convey structured failure details (error code, message,
retryability) so consumers get webhook failure context without relying on a
non-standard status code.

---

Nitpick comments:
In
`@clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionClient.java`:
- Around line 227-352: Update the Javadoc `@throws` entries for WebhookFailed in
the affected methods (e.g., bulkOperation(BulkOperationInput),
concludeExperiment(ConcludeExperimentInput), createContext(CreateContextInput),
createDefaultConfig(CreateDefaultConfigInput),
createDimension(CreateDimensionInput), createExperiment(CreateExperimentInput)
and other listed ranges) to explicitly state that WebhookFailed indicates the
server-side operation completed but delivery of the webhook notification failed
(i.e., operation succeeded but webhook notification failed), so clients do not
treat it as a full mutation failure; apply the same short qualifier to every
`@throws` WebhookFailed line in the indicated sections.

In `@docs/docs/api/move-context.api.mdx`:
- Line 8: The encoded api frontmatter blob in move-context.api.mdx is a
generated/expected artifact causing secret-scan false positives; add a targeted
allowlist rule in the secret-scan config (allowlist/exceptions) that whitelists
this docs path and/or frontmatter key "api" for generated blobs, and document
the exception with a short rationale; ensure the rule specifically targets the
file pattern docs/docs/api/*.mdx and the frontmatter key "api" to avoid broad
suppression.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aac0ba6 and fabc068.

📒 Files selected for processing (143)
  • clients/haskell/sdk/Io/Superposition/Command/BulkOperation.hs
  • clients/haskell/sdk/Io/Superposition/Command/ConcludeExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/CreateContext.hs
  • clients/haskell/sdk/Io/Superposition/Command/CreateDefaultConfig.hs
  • clients/haskell/sdk/Io/Superposition/Command/CreateDimension.hs
  • clients/haskell/sdk/Io/Superposition/Command/CreateExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/DeleteContext.hs
  • clients/haskell/sdk/Io/Superposition/Command/DeleteDefaultConfig.hs
  • clients/haskell/sdk/Io/Superposition/Command/DeleteDimension.hs
  • clients/haskell/sdk/Io/Superposition/Command/DiscardExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/GetContextFromCondition.hs
  • clients/haskell/sdk/Io/Superposition/Command/MoveContext.hs
  • clients/haskell/sdk/Io/Superposition/Command/PauseExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/RampExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/ResumeExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/UpdateDefaultConfig.hs
  • clients/haskell/sdk/Io/Superposition/Command/UpdateDimension.hs
  • clients/haskell/sdk/Io/Superposition/Command/UpdateOverride.hs
  • clients/haskell/sdk/Io/Superposition/Command/UpdateOverridesExperiment.hs
  • clients/haskell/sdk/Io/Superposition/Command/WeightRecompute.hs
  • clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs
  • clients/haskell/sdk/SuperpositionSDK.cabal
  • clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionAsyncClient.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/client/SuperpositionClient.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/BulkOperation.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/ConcludeExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateContext.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateDefaultConfig.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateDimension.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/CreateExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteContext.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteDefaultConfig.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/DeleteDimension.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/DiscardExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/GetContextFromCondition.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/MoveContext.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/PauseExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/RampExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/ResumeExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateDefaultConfig.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateDimension.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateOverride.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/UpdateOverridesExperiment.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/WebhookFailed.java
  • clients/java/sdk/src/main/java/io/juspay/superposition/model/WeightRecompute.java
  • clients/javascript/sdk/src/commands/BulkOperationCommand.ts
  • clients/javascript/sdk/src/commands/ConcludeExperimentCommand.ts
  • clients/javascript/sdk/src/commands/CreateContextCommand.ts
  • clients/javascript/sdk/src/commands/CreateDefaultConfigCommand.ts
  • clients/javascript/sdk/src/commands/CreateDimensionCommand.ts
  • clients/javascript/sdk/src/commands/CreateExperimentCommand.ts
  • clients/javascript/sdk/src/commands/DeleteContextCommand.ts
  • clients/javascript/sdk/src/commands/DeleteDefaultConfigCommand.ts
  • clients/javascript/sdk/src/commands/DeleteDimensionCommand.ts
  • clients/javascript/sdk/src/commands/DiscardExperimentCommand.ts
  • clients/javascript/sdk/src/commands/GetContextFromConditionCommand.ts
  • clients/javascript/sdk/src/commands/MoveContextCommand.ts
  • clients/javascript/sdk/src/commands/PauseExperimentCommand.ts
  • clients/javascript/sdk/src/commands/RampExperimentCommand.ts
  • clients/javascript/sdk/src/commands/ResumeExperimentCommand.ts
  • clients/javascript/sdk/src/commands/UpdateDefaultConfigCommand.ts
  • clients/javascript/sdk/src/commands/UpdateDimensionCommand.ts
  • clients/javascript/sdk/src/commands/UpdateOverrideCommand.ts
  • clients/javascript/sdk/src/commands/UpdateOverridesExperimentCommand.ts
  • clients/javascript/sdk/src/commands/WeightRecomputeCommand.ts
  • clients/javascript/sdk/src/models/models_0.ts
  • clients/javascript/sdk/src/protocols/Aws_restJson1.ts
  • clients/python/sdk/superposition_sdk/_private/schemas.py
  • clients/python/sdk/superposition_sdk/deserialize.py
  • clients/python/sdk/superposition_sdk/models.py
  • crates/superposition_sdk/src/error_meta.rs
  • crates/superposition_sdk/src/operation/bulk_operation.rs
  • crates/superposition_sdk/src/operation/conclude_experiment.rs
  • crates/superposition_sdk/src/operation/create_context.rs
  • crates/superposition_sdk/src/operation/create_default_config.rs
  • crates/superposition_sdk/src/operation/create_dimension.rs
  • crates/superposition_sdk/src/operation/create_experiment.rs
  • crates/superposition_sdk/src/operation/delete_context.rs
  • crates/superposition_sdk/src/operation/delete_default_config.rs
  • crates/superposition_sdk/src/operation/delete_dimension.rs
  • crates/superposition_sdk/src/operation/discard_experiment.rs
  • crates/superposition_sdk/src/operation/get_context_from_condition.rs
  • crates/superposition_sdk/src/operation/move_context.rs
  • crates/superposition_sdk/src/operation/pause_experiment.rs
  • crates/superposition_sdk/src/operation/ramp_experiment.rs
  • crates/superposition_sdk/src/operation/resume_experiment.rs
  • crates/superposition_sdk/src/operation/update_default_config.rs
  • crates/superposition_sdk/src/operation/update_dimension.rs
  • crates/superposition_sdk/src/operation/update_override.rs
  • crates/superposition_sdk/src/operation/update_overrides_experiment.rs
  • crates/superposition_sdk/src/operation/weight_recompute.rs
  • crates/superposition_sdk/src/protocol_serde.rs
  • crates/superposition_sdk/src/protocol_serde/shape_bulk_operation.rs
  • crates/superposition_sdk/src/protocol_serde/shape_conclude_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_create_context.rs
  • crates/superposition_sdk/src/protocol_serde/shape_create_default_config.rs
  • crates/superposition_sdk/src/protocol_serde/shape_create_dimension.rs
  • crates/superposition_sdk/src/protocol_serde/shape_create_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_delete_context.rs
  • crates/superposition_sdk/src/protocol_serde/shape_delete_default_config.rs
  • crates/superposition_sdk/src/protocol_serde/shape_delete_dimension.rs
  • crates/superposition_sdk/src/protocol_serde/shape_discard_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_get_context_from_condition.rs
  • crates/superposition_sdk/src/protocol_serde/shape_move_context.rs
  • crates/superposition_sdk/src/protocol_serde/shape_pause_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_ramp_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_resume_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_update_default_config.rs
  • crates/superposition_sdk/src/protocol_serde/shape_update_dimension.rs
  • crates/superposition_sdk/src/protocol_serde/shape_update_override.rs
  • crates/superposition_sdk/src/protocol_serde/shape_update_overrides_experiment.rs
  • crates/superposition_sdk/src/protocol_serde/shape_webhook_failed.rs
  • crates/superposition_sdk/src/protocol_serde/shape_weight_recompute.rs
  • crates/superposition_sdk/src/types/error.rs
  • crates/superposition_sdk/src/types/error/_webhook_failed.rs
  • crates/superposition_sdk/src/types/error/builders.rs
  • docs/docs/api/Superposition.openapi.json
  • docs/docs/api/bulk-operation.api.mdx
  • docs/docs/api/conclude-experiment.api.mdx
  • docs/docs/api/create-context.api.mdx
  • docs/docs/api/create-default-config.api.mdx
  • docs/docs/api/create-dimension.api.mdx
  • docs/docs/api/create-experiment.api.mdx
  • docs/docs/api/delete-context.api.mdx
  • docs/docs/api/delete-default-config.api.mdx
  • docs/docs/api/delete-dimension.api.mdx
  • docs/docs/api/discard-experiment.api.mdx
  • docs/docs/api/get-context-from-condition.api.mdx
  • docs/docs/api/move-context.api.mdx
  • docs/docs/api/pause-experiment.api.mdx
  • docs/docs/api/ramp-experiment.api.mdx
  • docs/docs/api/resume-experiment.api.mdx
  • docs/docs/api/update-default-config.api.mdx
  • docs/docs/api/update-dimension.api.mdx
  • docs/docs/api/update-override.api.mdx
  • docs/docs/api/update-overrides-experiment.api.mdx
  • docs/docs/api/weight-recompute.api.mdx
  • smithy/models/context.smithy
  • smithy/models/default-config.smithy
  • smithy/models/dimension.smithy
  • smithy/models/experiments.smithy
  • smithy/models/main.smithy
  • smithy/patches/python.patch



instance Io.Superposition.Utility.FromResponseParser WebhookFailed where
expectedStatus = Network.HTTP.Types.status512
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read the relevant section
fd "WebhookFailed.hs" --type f

Repository: juspay/superposition

Length of output: 123


🏁 Script executed:

# Get the file content around line 55 to see the actual code
if [ -f "clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs" ]; then
  cat -n "clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs" | head -70 | tail -30
fi

Repository: juspay/superposition

Length of output: 1022


🏁 Script executed:

# Search for imports and Network.HTTP.Types usage in the file
if [ -f "clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs" ]; then
  cat -n "clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs" | head -20
fi

Repository: juspay/superposition

Length of output: 704


🏁 Script executed:

# Check for http-types cabal or package.yaml to understand the library version
fd "package.yaml|*.cabal" --type f | grep -E "(package\.yaml|\.cabal)$" | head -5

Repository: juspay/superposition

Length of output: 376


🏁 Script executed:

# Search for other status definitions in the codebase to understand the pattern
rg -n "mkStatus|status\d+" --type=hs | head -20

Repository: juspay/superposition

Length of output: 2503


🏁 Script executed:

# Find package.yaml or .cabal files
fd -g "package.yaml" -o -g "*.cabal" --type f

Repository: juspay/superposition

Length of output: 180


🏁 Script executed:

# Search for mkStatus usage in the codebase
rg "mkStatus" --type=hs

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Check if there's any documentation or imports related to Status construction
rg "Network.HTTP.Types.Status" --type=hs

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Simpler search for cabal and package files
find . -maxdepth 3 -name "*.cabal" -o -name "package.yaml" | head -10

Repository: juspay/superposition

Length of output: 46


🌐 Web query:

http-types Haskell mkStatus function API documentation

💡 Result:

In the http-types Haskell package, mkStatus is defined in Network.HTTP.Types.Status (and re-exported from Network.HTTP.Types). It constructs an HTTP Status from a numeric code and a reason phrase. [1][2]

mkStatus :: Int -> ByteString -> Status

[2]

Notes from the API docs:

  • Status comparisons (Eq/Ord) use only statusCode. [1]
  • You should prefer mkStatus, the Enum instance, or predefined constants (e.g. ok200) instead of constructing Status directly, because the record may gain additional fields in the future. [1]
  • In the Enum instance, unknown codes fall back to mkStatus c "" (empty message). [2]

Sources: Hackage documentation for Network.HTTP.Types.Status and the module source. [1][2]


🏁 Script executed:

# Check for OverloadedStrings extension usage
rg "OverloadedStrings" --type=hs

Repository: juspay/superposition

Length of output: 134


🏁 Script executed:

# Search for ByteString imports and usage
rg "ByteString|Data.ByteString" --type=hs | head -10

Repository: juspay/superposition

Length of output: 1149


🏁 Script executed:

# Check the cabal/package config at root level
ls -la *.cabal *.yaml 2>/dev/null || echo "No cabal/yaml files at root"

Repository: juspay/superposition

Length of output: 160


🏁 Script executed:

# Check if WebhookFailed.hs has OverloadedStrings pragma
head -20 clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs | grep -i language

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Check what other Model files use for their pragmas
find clients/haskell/sdk/Io/Superposition/Model -name "*.hs" -type f | head -3 | xargs head -5

Repository: juspay/superposition

Length of output: 666


🏁 Script executed:

# Show the first 15 lines of WebhookFailed.hs to check for pragmas
head -15 clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs

Repository: juspay/superposition

Length of output: 460


🏁 Script executed:

# Check how other Model files handle status parsing with similar structure
grep -A 3 "expectedStatus =" clients/haskell/sdk/Io/Superposition/Model/ResourceNotFound.hs

Repository: juspay/superposition

Length of output: 155


🏁 Script executed:

# Look at a similar file to see the full context
cat -n clients/haskell/sdk/Io/Superposition/Model/ResourceNotFound.hs | head -20

Repository: juspay/superposition

Length of output: 719


🏁 Script executed:

# Search for any mkStatus usage or imports of Status module
rg "mkStatus|Network.HTTP.Types.Status" --type=hs -B 2 -A 2

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Check if there are any imports of Char8 or other ByteString constructors in Model files
rg "import.*ByteString|import.*Char8" clients/haskell/sdk/Io/Superposition/Model/ --type=hs

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Search for any CI logs or error messages related to compilation
find . -name "*.log" -o -name "*build*output*" 2>/dev/null | head -5

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Check git history or recent changes to see if there's any context on this
git log --oneline -20 -- clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs 2>/dev/null || echo "No git history available"

Repository: juspay/superposition

Length of output: 161


🏁 Script executed:

# Search the entire codebase for how ByteString is typically handled with status or similar constructions
rg "BC\.pack|Data\.ByteString\.Char8" --type=hs | head -5

Repository: juspay/superposition

Length of output: 173


🏁 Script executed:

# Let's check what the proper way to create a ByteString in this codebase style would be
# by looking at actual usage patterns
rg "ByteString" clients/haskell/sdk/Io/Superposition/Model/*.hs | head -20

Repository: juspay/superposition

Length of output: 46


🏁 Script executed:

# Check if there are any examples of string to ByteString conversions in the codebase
rg "pack|unpack" clients/haskell/sdk/Io/Superposition/Model/ --type=hs

Repository: juspay/superposition

Length of output: 17869


🏁 Script executed:

# Let's search for cabal files more carefully
find clients/haskell -name "*.cabal" -type f 2>/dev/null | head -5

Repository: juspay/superposition

Length of output: 322


🏁 Script executed:

# Check if there's a default-extensions section that might apply to all modules
find clients/haskell -name "*.cabal" -type f -exec cat {} \; 2>/dev/null | grep -A 10 -i "default-extensions\|extensions" | head -30

Repository: juspay/superposition

Length of output: 678


🏁 Script executed:

# Check the SuperpositionSDK.cabal file for default-extensions including OverloadedStrings
cat clients/haskell/sdk/SuperpositionSDK.cabal | grep -A 50 "default-extensions"

Repository: juspay/superposition

Length of output: 629


status512 is not exported; this currently breaks compilation.

Line 55 uses Network.HTTP.Types.status512, which does not exist in http-types. Define a custom status with mkStatus instead. With OverloadedStrings enabled in the SDK configuration, the string literal will be automatically coerced to the required ByteString type.

🔧 Proposed fix
-import qualified Network.HTTP.Types
+import qualified Network.HTTP.Types.Status

 instance Io.Superposition.Utility.FromResponseParser WebhookFailed where
-    expectedStatus = Network.HTTP.Types.status512
+    expectedStatus = Network.HTTP.Types.Status.mkStatus 512 "WebhookFailed"
     responseParser = do
🧰 Tools
🪛 GitHub Actions: CI Nix

[error] 55-55: Not in scope: Network.HTTP.Types.status512. The module Network.HTTP.Types does not export status512. Consider using a valid status code such as status412, status502, or status511.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/haskell/sdk/Io/Superposition/Model/WebhookFailed.hs` at line 55, The
reference to Network.HTTP.Types.status512 in WebhookFailed.hs breaks compilation
because status512 isn't exported; replace the usage of expectedStatus with a
custom status created via Network.HTTP.Types.mkStatus (e.g., mkStatus 512
"Webhook Failed") so the module defines expectedStatus using mkStatus instead of
the non-existent status512; keep OverloadedStrings enabled so the reason phrase
literal is coerced correctly.

Comment on lines 679 to 680
ShapeID("smithy.api#httpBasicAuth")
ShapeID("smithy.api#httpBearerAuth")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="clients/python/sdk/superposition_sdk/models.py"

echo "== AST parse check =="
python - <<'PY'
import ast, pathlib, sys
p = pathlib.Path("clients/python/sdk/superposition_sdk/models.py")
src = p.read_text(encoding="utf-8")
try:
    ast.parse(src)
    print("✓ OK: models.py parses without syntax errors")
except SyntaxError as e:
    print(f"✗ SYNTAX_ERROR: {e.msg} at line {e.lineno}, column {e.offset}")
    sys.exit(1)
PY

echo
echo "== Inspect lines 679-680 (main issue) =="
sed -n '676,683p' "$FILE" | cat -n

echo
echo "== Inspect lines 881-882 =="
sed -n '878,885p' "$FILE" | cat -n

echo
echo "== Inspect lines 1155-1156 =="
sed -n '1152,1159p' "$FILE" | cat -n

Repository: juspay/superposition

Length of output: 168


🏁 Script executed:

#!/bin/bash

FILE="clients/python/sdk/superposition_sdk/models.py"

echo "== Context around line 679 (main issue) =="
sed -n '676,684p' "$FILE" | cat -n

echo
echo "== Context around line 881 =="
sed -n '878,886p' "$FILE" | cat -n

echo
echo "== Context around line 1155 =="
sed -n '1152,1160p' "$FILE" | cat -n

echo
echo "== Check first occurrence of missing comma pattern =="
rg -n -B2 -A2 'ShapeID\("smithy\.api#http(Basic|Bearer)Auth"\)' "$FILE" | head -40

Repository: juspay/superposition

Length of output: 2200


Fix missing commas in effective_auth_schemes list elements—syntax error breaks module parsing.

Adjacent ShapeID(...) entries lack comma separators, breaking Python syntax. This prevents the module from being imported. The issue appears in multiple effective_auth_schemes blocks throughout the file.

Fix pattern
         effective_auth_schemes = [
-            ShapeID("smithy.api#httpBasicAuth")
-            ShapeID("smithy.api#httpBearerAuth")
+            ShapeID("smithy.api#httpBasicAuth"),
+            ShapeID("smithy.api#httpBearerAuth"),
         ]

Affected locations: 679–680, 881–882, 1155–1156, 1953–1954, 2243–2244, 2753–2756, and others.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ShapeID("smithy.api#httpBasicAuth")
ShapeID("smithy.api#httpBearerAuth")
ShapeID("smithy.api#httpBasicAuth"),
ShapeID("smithy.api#httpBearerAuth"),
🧰 Tools
🪛 Ruff (0.15.2)

[warning] 680-680: Expected ,, found name

(invalid-syntax)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/python/sdk/superposition_sdk/models.py` around lines 679 - 680, The
problem is missing comma separators between adjacent ShapeID entries inside
effective_auth_schemes lists which causes a SyntaxError; locate every occurrence
of the variable/attribute named effective_auth_schemes in models.py (e.g., the
lists containing ShapeID("smithy.api#httpBasicAuth") and
ShapeID("smithy.api#httpBearerAuth")) and add a comma between each ShapeID(...)
element so each list item is properly separated; apply this fix to all reported
locations (around the blocks containing those ShapeID entries near the noted
occurrences) and run an import/syntax check to verify the module parses.

id={undefined}
label={undefined}
responses={{"200":{"description":"BulkOperation 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"type":"array","items":{"oneOf":[{"type":"object","title":"PUT","properties":{"PUT":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["PUT"]},{"type":"object","title":"REPLACE","properties":{"REPLACE":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["REPLACE"]},{"type":"object","title":"DELETE","properties":{"DELETE":{"type":"string"}},"required":["DELETE"]},{"type":"object","title":"MOVE","properties":{"MOVE":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["MOVE"]}],"title":"ContextActionOut"}}},"required":["output"],"title":"BulkOperationResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}}}}
responses={{"200":{"description":"BulkOperation 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"type":"array","items":{"oneOf":[{"type":"object","title":"PUT","properties":{"PUT":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["PUT"]},{"type":"object","title":"REPLACE","properties":{"REPLACE":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["REPLACE"]},{"type":"object","title":"DELETE","properties":{"DELETE":{"type":"string"}},"required":["DELETE"]},{"type":"object","title":"MOVE","properties":{"MOVE":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"ContextResponse"}},"required":["MOVE"]}],"title":"ContextActionOut"}}},"required":["output"],"title":"BulkOperationResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}},"512":{"description":"WebhookFailed 512 response"}}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document the 512 payload contract explicitly.

Line 65 adds WebhookFailed 512 response with description only. Given the command docs state the response body contains the successful operation result, this status code should also declare its response schema/content to avoid ambiguity for API consumers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/bulk-operation.api.mdx` at line 65, The 512 "WebhookFailed"
response currently has only a description—add an explicit response body schema
under the 512 entry (e.g., "content":{"application/json":{"schema":{...}}}) so
API consumers know the payload; reuse or reference the existing
"BulkOperationResponseContent" schema used for the 200 response (the object
titled BulkOperationResponseContent / ContextActionOut) so the 512 returns the
same successful-operation result shape as documented for other command
responses.

id={undefined}
label={undefined}
responses={{"200":{"description":"CreateDimension 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"dimension":{"type":"string"},"position":{"type":"number"},"schema":{"type":"object","additionalProperties":{},"description":"Generic key-value object structure used for flexible data representation throughout the API.","title":"Object"},"value_validation_function_name":{"type":"string"},"description":{"type":"string"},"change_reason":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"dependency_graph":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"title":"DependencyGraph"},"dimension_type":{"oneOf":[{"type":"object","title":"REGULAR","properties":{"REGULAR":{"type":"object","title":"Unit"}},"required":["REGULAR"]},{"type":"object","title":"LOCAL_COHORT","properties":{"LOCAL_COHORT":{"type":"string"}},"required":["LOCAL_COHORT"]},{"type":"object","title":"REMOTE_COHORT","properties":{"REMOTE_COHORT":{"type":"string"}},"required":["REMOTE_COHORT"]}],"title":"DimensionType"},"value_compute_function_name":{"type":"string"},"mandatory":{"type":"boolean"}},"required":["change_reason","created_at","created_by","dependency_graph","description","dimension","dimension_type","last_modified_at","last_modified_by","mandatory","position","schema"],"title":"CreateDimensionResponseContent"}}}},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}}}}
responses={{"200":{"description":"CreateDimension 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"dimension":{"type":"string"},"position":{"type":"number"},"schema":{"type":"object","additionalProperties":{},"description":"Generic key-value object structure used for flexible data representation throughout the API.","title":"Object"},"value_validation_function_name":{"type":"string"},"description":{"type":"string"},"change_reason":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"dependency_graph":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"title":"DependencyGraph"},"dimension_type":{"oneOf":[{"type":"object","title":"REGULAR","properties":{"REGULAR":{"type":"object","title":"Unit"}},"required":["REGULAR"]},{"type":"object","title":"LOCAL_COHORT","properties":{"LOCAL_COHORT":{"type":"string"}},"required":["LOCAL_COHORT"]},{"type":"object","title":"REMOTE_COHORT","properties":{"REMOTE_COHORT":{"type":"string"}},"required":["REMOTE_COHORT"]}],"title":"DimensionType"},"value_compute_function_name":{"type":"string"},"mandatory":{"type":"boolean"}},"required":["change_reason","created_at","created_by","dependency_graph","description","dimension","dimension_type","last_modified_at","last_modified_by","mandatory","position","schema"],"title":"CreateDimensionResponseContent"}}}},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}},"512":{"description":"WebhookFailed 512 response"}}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Document the 512 response payload shape explicitly.

Line 65 adds WebhookFailed 512 with only a description, but the SDK docs describe a meaningful response body for this case. Please include the actual content schema (or explicitly document empty body) so the API contract is unambiguous for client integrators and generators.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/create-dimension.api.mdx` at line 65, The 512 WebhookFailed
entry under the responses object in CreateDimension response currently only has
a description; update the responses["512"] entry (in the same responses object
that contains "200" and "500") to explicitly specify the response payload:
either add a content section with "application/json" and the correct schema that
matches the SDK's WebhookFailed body (e.g., properties like message, webhook_id,
details as appropriate) or explicitly document an empty body by setting content
to an empty object; ensure the symbol to change is the responses["512"] block so
the API contract is unambiguous for client generators.

id={undefined}
label={undefined}
responses={{"200":{"description":"MoveContext 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"MoveContextResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}}}}
responses={{"200":{"description":"MoveContext 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"MoveContextResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}},"512":{"description":"WebhookFailed 512 response"}}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a response schema for 512 WebhookFailed to keep docs contract explicit.

Right now 512 only has a description. Please include a content schema (similar to other error responses) so clients can see the exact payload shape.

📝 Proposed docs patch
- "512":{"description":"WebhookFailed 512 response"}
+ "512":{"description":"WebhookFailed 512 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"WebhookFailedResponseContent"}}}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
responses={{"200":{"description":"MoveContext 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"MoveContextResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}},"512":{"description":"WebhookFailed 512 response"}}}
responses={{"200":{"description":"MoveContext 200 response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"object","additionalProperties":{},"description":"Represents conditional criteria used for context matching. Keys define dimension names and values specify the criteria that must be met.","title":"Condition"},"override":{"type":"object","additionalProperties":{},"description":"Configuration overrides that replace default values when context conditions are met. Keys represent configuration keys and values are the override data.","title":"Overrides"},"override_id":{"type":"string"},"weight":{"type":"string","description":"Priority weight used to determine the order of context evaluation. Higher weights take precedence during configuration resolution."},"description":{"type":"string"},"change_reason":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string"},"last_modified_at":{"type":"string","format":"date-time"},"last_modified_by":{"type":"string"}},"required":["change_reason","created_at","created_by","description","id","last_modified_at","last_modified_by","override","override_id","value","weight"],"title":"MoveContextResponseContent"}}}},"404":{"description":"ResourceNotFound 404 response"},"500":{"description":"InternalServerError 500 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"InternalServerErrorResponseContent"}}}},"512":{"description":"WebhookFailed 512 response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"title":"WebhookFailedResponseContent"}}}}}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/move-context.api.mdx` at line 65, The 512 response currently
only has a description; add a content schema for the 512 WebhookFailed response
mirroring other error responses (e.g., like the 500 InternalServerError). Update
the responses block for MoveContext so 512 includes application/json content
with a schema object (type: "object") and a properties map containing at least
"message" (type: "string") and a title such as "WebhookFailedResponseContent" so
clients can see the exact payload shape; modify the same responses object where
"200", "404", and "500" are defined.

Comment on lines +697 to 699
"512": {
"description": "WebhookFailed 512 response"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's run the provided verification script to find all 512 responses without content
jq -r '
  .paths
  | to_entries[]
  | . as $path
  | $path.value
  | to_entries[]
  | select(.value.responses["512"] != null)
  | select(.value.responses["512"].content == null)
  | "\($path.key) \(.key)"
' docs/docs/api/Superposition.openapi.json 2>&1 | head -30

Repository: juspay/superposition

Length of output: 582


🏁 Script executed:

#!/bin/bash
# Check if WebhookFailedResponseContent exists in components.schemas
jq '.components.schemas | keys' docs/docs/api/Superposition.openapi.json 2>&1 | grep -i webhook || echo "No webhook schema found"

Repository: juspay/superposition

Length of output: 319


🏁 Script executed:

#!/bin/bash
# Count total 512 responses in the file
jq '
  .paths
  | to_entries[]
  | .value
  | to_entries[]
  | select(.value.responses["512"] != null)
' docs/docs/api/Superposition.openapi.json 2>&1 | grep -c "responses"

Repository: juspay/superposition

Length of output: 66


🏁 Script executed:

#!/bin/bash
# Get the structure of a sample 512 response block to see what exists
jq '.paths | to_entries[0].value | to_entries[0].value.responses["512"]' docs/docs/api/Superposition.openapi.json 2>&1

Repository: juspay/superposition

Length of output: 68


🏁 Script executed:

#!/bin/bash
# Let's get an actual 512 response structure from one of the found paths
jq '.paths["/context"].put.responses["512"]' docs/docs/api/Superposition.openapi.json 2>&1

Repository: juspay/superposition

Length of output: 113


🏁 Script executed:

#!/bin/bash
# Check the actual content at line 697 to verify it matches the comment
sed -n '695,700p' docs/docs/api/Superposition.openapi.json

Repository: juspay/superposition

Length of output: 250


🏁 Script executed:

#!/bin/bash
# Get exact line numbers where 512 appears in responses
grep -n '"512"' docs/docs/api/Superposition.openapi.json | head -25

Repository: juspay/superposition

Length of output: 738


🏁 Script executed:

#!/bin/bash
# Count exact matches of 512 in responses section
grep -c '"512"' docs/docs/api/Superposition.openapi.json

Repository: juspay/superposition

Length of output: 66


Add a typed response schema for all 512 blocks.

All 20 512 responses currently lack content definitions. Without typed schemas, SDKs will not generate proper typed WebhookFailed exceptions, defeating the PR objective.

The schema WebhookFailedResponseContent does not exist in components.schemas and must be created.

🔧 Proposed OpenAPI fix pattern
 "512": {
-  "description": "WebhookFailed 512 response"
+  "description": "WebhookFailed 512 response",
+  "content": {
+    "application/json": {
+      "schema": {
+        "$ref": "#/components/schemas/WebhookFailedResponseContent"
+      }
+    }
+  }
 }
 "components": {
   "schemas": {
+    "WebhookFailedResponseContent": {
+      "type": "object",
+      "properties": {
+        "message": { "type": "string" }
+      },
+      "required": ["message"]
+    },
     ...
   }
 }

Affects lines: 697, 769, 833, 906, 978, 1089, 1152, 1353, 1409, 1538, 1674, 1730, 1859, 2612, 2804, 2877, 2950, 3023, 3096, 3169.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/Superposition.openapi.json` around lines 697 - 699, Several
"512" response objects (e.g., the response block that currently has only
"description": "WebhookFailed 512 response") are missing a typed content schema;
add a content entry to each 512 response that uses "application/json" with
schema: { "$ref": "#/components/schemas/WebhookFailedResponseContent" } and then
create the components.schemas.WebhookFailedResponseContent definition (include
fields matching the WebhookFailed error model such as an error code, message,
optional details/metadata and any id/timestamp used elsewhere) so SDKs can
generate typed WebhookFailed exceptions; update every 512 block referenced (all
occurrences of the "WebhookFailed 512 response") to reference this new schema
name.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

HTTP status code 512 RFC 9110 IANA standard

💡 Result:

HTTP 512 is not an IANA-registered / RFC 9110-defined HTTP status code, so it is not a standard HTTP response status.

  • In the IANA HTTP Status Code Registry (referenced by RFC 9110), codes 512–599 are “Unassigned”; the last assigned codes in that area are 511 (Network Authentication Required) and then 512–599 unassigned. [1]
  • RFC 9110 specifies that HTTP status codes are extensible, and a client must treat an unrecognized status code as equivalent to the x00 code of that class (so an unknown 512 would be treated like 500), and that only 100–599 are valid status codes. [2]

Sources
[1] IANA “Hypertext Transfer Protocol (HTTP) Status Code Registry” (shows “512-599 Unassigned”)
[2] RFC 9110 (HTTP Semantics), status code handling rules (unrecognized codes → x00 of the class; valid range 100..599)


🌐 Web query:

how API gateways proxies handle unknown 5xx status codes

💡 Result:

Most API gateways / reverse proxies treat an “unknown” 5xx (e.g., 598, 599, or any unrecognized 5xx) as just another server-error-class response:

  • HTTP semantics (what clients/gateways are expected to do): HTTP status codes are extensible; recipients must understand the class (first digit) and treat an unrecognized status code as equivalent to x00 of that class (so an unknown 5xx is treated like 500 for generic handling purposes). They may still forward the original code. [1]

  • Transparent proxy behavior (common default): Many gateways are “transparent” by default and simply proxy upstream responses downstream (status code, headers, body) unless configured to transform them.

    • Kong Gateway: Describes itself as a transparent proxy and states it receives the upstream response and sends it back to the downstream client (streaming). If a plugin rewrites the response, Kong can emit X-Kong-Upstream-Status so clients can still see what the upstream returned. [2][3]
  • NGINX / NGINX-based gateways (pass-through vs intercept):

    • With proxy_intercept_errors off (default), NGINX will pass upstream responses (including 5xx) to the client.
    • If proxy_intercept_errors on, NGINX can intercept responses with status >= 300 and generate a synthetic response via error_page (often mapping “odd/unknown 5xx” into a standardized error payload/status). [4]
  • Envoy-style proxies (pass-through, but may generate their own 5xx on upstream failure):

    • Envoy’s request lifecycle describes that the request is proxied upstream and the response is proxied downstream through filters. [5]
    • Separately, health/outlier features can change what clients see: e.g., after repeated upstream 5xx, Envoy can eject hosts; if no healthy hosts remain it can return a local 503 (“no healthy host…”). [6]
  • Managed API gateways often distinguish “upstream returned 5xx” vs “gateway couldn’t reach upstream”:

    • AWS API Gateway: Has distinct gateway response types like DEFAULT_5XX, INTEGRATION_FAILURE, INTEGRATION_TIMEOUT (commonly surfaced as 504 for integration failure/timeout) and others. So an upstream “unknown 5xx” might be passed through (depending on integration type/mapping), while connection/timeouts become gateway-generated errors. [7]
    • For Lambda + API Gateway, invocation/function/format errors can be converted into 500/502 with a generic body, unless you handle and format errors explicitly. [8]
  • Apigee Edge: By default, backend 4xx–5xx responses are treated as failures that put the proxy into an error state (fault flow), which you can override/custom-handle (e.g., via success.codes or FaultRules). [9]

Practical takeaway:
If the upstream actually returns an unrecognized 5xx, most proxies will forward it unchanged unless you’ve enabled error interception / fault rules / response rewriting. But if the gateway itself can’t complete the upstream call (timeout, reset, no healthy targets), it will usually emit a standard gateway-generated 5xx (often 502/503/504) instead of the upstream code. [4][6][7]

Sources
[1] RFC 9110 (HTTP Semantics) – unrecognized status codes treated as x00 of their class: https://www.rfc-editor.org/rfc/inline-errata/rfc9110.html
[2] Kong Gateway “routing/proxying traffic” (transparent proxy; proxies response back): https://docs.konghq.com/gateway/latest/how-kong-works/routing-traffic/
[3] Kong configuration reference (X-Kong-Upstream-Status header): https://docs.konghq.com/gateway/latest/reference/configuration/
[4] NGINX proxy_intercept_errors directive (intercepts codes >= 300 for error_page handling; default off): https://nginx.org/r/proxy_ignore_client_abort
[5] Envoy “Life of a Request” (response proxied downstream through filters): https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request.html
[6] HashiCorp (Envoy) outlier detection leading to 503 “no healthy host…”: https://support.hashicorp.com/hc/en-us/articles/20777919636115-Troubleshooting-Consul-Envoy-503-Error-No-Healthy-Host-for-HTTP-Connection-Pool
[7] AWS API Gateway “gateway response types” (DEFAULT_5XX, INTEGRATION_FAILURE/TIMEOUT, etc.): https://docs.aws.amazon.com/apigateway/latest/developerguide/supported-gateway-response-types.html
[8] AWS Lambda docs on API Gateway returning 500/502 for invocation/function/format errors: https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway-errors.html
[9] Apigee Edge fault handling (4xx–5xx treated as failure by default; customizable): https://docs.apigee.com/api-platform/fundamentals/fault-handling


🌐 Web query:

HTTP 512 WebhookFailed status code specification

💡 Result:

There is no official/standard HTTP status code 512, and there is no IETF/IANA “WebhookFailed” HTTP status.

  • HTTP status codes are 3-digit and only defined in the range 100–599. Unknown codes must be treated as their “x00” class equivalent (so an unknown 5xx is treated like 500). [2]
  • In the IANA HTTP Status Code Registry, 511 is the last assigned 5xx code, and 512–599 are “Unassigned.” [1]
  • 511 Network Authentication Required is specified in RFC 6585 (not 512). [3]

So if you’re seeing HTTP 512 WebhookFailed, it’s a non-standard, vendor/application-defined code (or possibly an internal error mapping), not an Internet standard. Use a registered HTTP status code (commonly 4xx for client issues, 5xx for server issues) and put “webhook failed” details in the response body/error payload instead. [1][2]

Sources:
[1] IANA HTTP Status Code Registry (shows 512–599 Unassigned)
[2] RFC 9110 (status code range + handling unknown codes)
[3] RFC 6585 / MDN (defines 511 Network Authentication Required)


Replace non-standard HTTP 512 with a standard status code before finalizing the contract.

HTTP 512 is not registered in the IANA HTTP Status Code Registry (RFC 9110). RFC 9110 mandates that clients treat unrecognized 5xx codes as 500, and gateway/proxy behavior is inconsistent: transparent proxies forward it unchanged, some intercept and normalize to 500, and managed gateways apply custom fault rules. This inconsistency will cause interoperability issues across different SDK/gateway implementations. Use a standard status code (e.g., 400 for client issues, 500/503 for server issues) and convey webhook failure details in the response body instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/docs/api/Superposition.openapi.json` around lines 697 - 699, The OpenAPI
response entry using the non-standard status key "512" (description
"WebhookFailed 512 response") must be changed to a standard HTTP status code
(e.g., replace "512" with "500" or "503" depending on whether it's a transient
server error) and update the response description accordingly; also add or
update a response body schema for the "WebhookFailed" response to convey
structured failure details (error code, message, retryability) so consumers get
webhook failure context without relying on a non-standard status code.

@documentation("Indicates that the operation succeeded but the webhook call failed. The response body contains the successful result, but the client should be aware that webhook notification did not complete.")
@httpError(512)
@error("server")
structure WebhookFailed {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, I think the consumer will not get the expected result back out of the call

@sauraww sauraww force-pushed the feat/webhook-smithy branch from fabc068 to 3cac133 Compare March 2, 2026 11:09
@sauraww sauraww force-pushed the feat/webhook-smithy branch from 3cac133 to 8defefa Compare March 3, 2026 10:34
@error("server")
structure WebhookFailed {
@documentation("The successful operation result that would have been returned with HTTP 200. The structure matches the operation's normal output type.")
data: Document
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this gives me the data back, but in raw format and not parsed
the consumer needs to handle this case manually and parse the data to get the actual response, right ?

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.

3 participants