Skip to content

added ProgramWalletBalanceResp type#1154

Open
Hari-Krishna-Dupaguntla wants to merge 1 commit into
mainfrom
feat_added_insert_query
Open

added ProgramWalletBalanceResp type#1154
Hari-Krishna-Dupaguntla wants to merge 1 commit into
mainfrom
feat_added_insert_query

Conversation

@Hari-Krishna-Dupaguntla
Copy link
Copy Markdown
Contributor

@Hari-Krishna-Dupaguntla Hari-Krishna-Dupaguntla commented Mar 2, 2026

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates

Description

Additional Changes

  • This PR modifies the database schema (database migration added)
  • This PR modifies dhall configs/environment variables

Motivation and Context

How did you test it?

Checklist

  • I formatted the code and addressed linter errors ./dev/format-all-files.sh
  • I reviewed submitted code
  • I added unit tests for my changes where possible
  • I added a CHANGELOG entry if applicable

Summary by CodeRabbit

  • New Features
    • Added configurable payment rules to create payments/orders for finer payment flow control.
    • Included loyalty program data in payment responses and order status for richer reporting.
    • Added expanded transaction details and amount-breakup information in status responses.
    • Exposed a loyalty-info wallet API to query program and customer loyalty details.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 1, 2026

Walkthrough

Adds paymentRules to create payment/order requests, enriches order status responses with loyaltyInfo and txnList, expands Juspay and PaytmEDC types for loyalty/transaction details, and introduces a new Juspay wallet loyaltyInfo flow with DTOs, config, and API client integration.

Changes

Cohort / File(s) Summary
Payment Interface Core
lib/mobility-core/src/Kernel/External/Payment/Interface.hs, lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs
Added optional paymentRules to CreateOrderReq/CreatePaymentReq; extended non-mandate OrderStatusResp with loyaltyInfo :: Maybe LoyaltyInfo and txnList :: Maybe [TxnList]; removed local TxnDetail in favor of Juspay types.
Juspay Integration (Interface & Types)
lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs, lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs, lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs
Mapped internal paymentRules into Juspay CreateOrderReq via new helpers; populated loyaltyInfo and txnList in order status conversions and webhook handlers; introduced extensive loyalty-related types and an expanded TxnDetail; added jsonSnakeOptions for snake_case JSON.
PaytmEDC Integration
lib/mobility-core/src/Kernel/External/Payment/Interface/PaytmEDC.hs, lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs
mkCreateOrderReq/status mapping updated to propagate loyalty and txn details; PaytmEDCResponseBody extended with loyaltyInfo and txnDetails.
Wallet Interface & Types
lib/mobility-core/src/Kernel/External/Wallet/Interface.hs, lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs
Added loyaltyInfo operation to wallet interface and introduced comprehensive Loyalty DTOs, JSON instances, and jsonSnakeOptions for request/response shapes.
Wallet Juspay Config & Flow
lib/mobility-core/src/Kernel/External/Wallet/Juspay/Config.hs, lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs, lib/mobility-core/src/Kernel/External/Wallet/Interface/Juspay.hs
Added LoyaltyCfg config type; implemented loyaltyInfo client flow (build auth header by decrypting apiKey, call Juspay loyalty API) and exposed loyaltyInfo in Wallet.Juspay interface.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant WalletIF as Wallet.Interface
  participant WalletJ as Wallet.Juspay
  participant JuspayFlow as Juspay.Flow
  participant External as Juspay API

  Client->>WalletIF: loyaltyInfo(LoyaltyCfg, LoyaltyInfoRequest)
  WalletIF->>WalletJ: loyaltyInfo(LoyaltyCfg, request)
  WalletJ->>WalletJ: decrypt apiKey, build Authorization header
  WalletJ->>JuspayFlow: loyaltyInfo(baseUrl, authHeader, merchantId, tenantId, request)
  JuspayFlow->>External: POST /loyalty/programs (headers + body)
  External-->>JuspayFlow: LoyaltyInfoResponse
  JuspayFlow-->>WalletJ: LoyaltyInfoResponse
  WalletJ-->>WalletIF: LoyaltyInfoResponse
  WalletIF-->>Client: LoyaltyInfoResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐇 I nibbled at rules and hopped through the maze,

tucked loyalty crumbs in JSON arrays,
Juspay and Paytm now share the feast,
transactions richer — a rabbit's small feast! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'added ProgramWalletBalanceResp type' does not match the actual changeset, which primarily implements payment rules support, loyalty info functionality across multiple payment/wallet modules, and transaction detail handling—with no mention of ProgramWalletBalanceResp in the provided changes. Update the PR title to accurately reflect the main changes, such as 'Add payment rules and loyalty info support to payment and wallet interfaces' or a similarly descriptive title that captures the core additions.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat_added_insert_query

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
Copy Markdown

@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: 2

🧹 Nitpick comments (3)
lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs (1)

235-235: Identity mapping in fieldLabelModifier is unnecessary but harmless.

The mapping "payment_rules" -> "payment_rules" is redundant since the other -> other fallback handles unmapped fields. However, keeping it explicit documents the field name used in the API.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs` at
line 235, Remove the redundant explicit mapping "payment_rules" ->
"payment_rules" from the fieldLabelModifier map in CreateOrder.hs; locate the
Aeson options (the fieldLabelModifier function or the record-to-JSON mapping in
the CreateOrder module) and delete that identity entry so the fallback clause
(other -> other) handles it, leaving any other explicit mappings intact.
lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs (1)

329-330: The empty Read instance is unusual but acceptable.

The Read instance returning [] (no valid parses) is a pragmatic workaround when a Read instance is required by a constraint but the type is too complex to parse from string representation. Consider adding a brief comment explaining this design choice.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs` around
lines 329 - 330, Add a short comment above the Read instance for TxnDetail
explaining why readsPrec always returns []: clarify that the instance is a
deliberate pragmatic stub to satisfy typeclass constraints (instance Read
TxnDetail with readsPrec _ _ = []) because TxnDetail is too complex or not
intended to be parsed from strings, and note that parsing is unsupported and any
attempt to read should fail; reference the instance declaration (instance Read
TxnDetail) and the readsPrec implementation to locate where to add the comment.
lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs (1)

734-735: Clarify the uncertainty comment.

The --Not Sure comment indicates uncertainty about whether txnList should be Nothing for the transaction-only webhook case. Consider investigating whether justTransaction contains a txn_list field that should be mapped, or document why Nothing is the correct value here.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs` around
lines 734 - 735, The comment warns that txnList is set to Nothing with
uncertainty; inspect the justTransaction value (and any field named txn_list)
and either map it into txnList or explicitly document why it must be Nothing for
transaction-only webhooks. Specifically, check the structure parsed into
justTransaction (look for a txn_list or similar field) and if present map it
into the txnList field (e.g., txnList = Just <mappedTxnList>), otherwise replace
the ambiguous comment with a clear comment explaining why txnList is
intentionally Nothing for the transaction-only webhook case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/mobility-core/src/Kernel/External/Payment/Interface.hs`:
- Around line 605-606: The PaytmEDC payment request construction includes an
unused field paymentRules (seen where CreateOrderReq is assembled with basket =
req.basket, paymentRules = req.paymentRules) but PaytmEDC only serializes a
PaytmEDCSaleRequestBody and never uses paymentRules; remove the paymentRules
assignment from the CreateOrderReq construction and any type/record fields
specific to PaytmEDC that reference paymentRules, update the
CreateOrderReq/PaytmEDC request type signatures and any callers to reflect the
removed field, and ensure PaytmEDCSaleRequestBody mapping continues to include
only the actual used fields (e.g., basket and other existing fields).

In `@lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs`:
- Around line 180-185: PaytmEDCResponseBody currently derives default
ToJSON/FromJSON (camelCase) while nested types LoyaltyInfo and TxnList use
jsonSnakeOptions (snake_case), causing deserialization mismatches; add explicit
instance declarations for FromJSON and ToJSON for PaytmEDCResponseBody using
jsonSnakeOptions (same options used by LoyaltyInfo and TxnList) so fields like
loyalty_info and txn_details parse correctly, or alternatively update
LoyaltyInfo/TxnList to match the parent — locate PaytmEDCResponseBody in
Types.hs and implement the jsonSnakeOptions-based instances to align names
across types.

---

Nitpick comments:
In `@lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs`:
- Around line 734-735: The comment warns that txnList is set to Nothing with
uncertainty; inspect the justTransaction value (and any field named txn_list)
and either map it into txnList or explicitly document why it must be Nothing for
transaction-only webhooks. Specifically, check the structure parsed into
justTransaction (look for a txn_list or similar field) and if present map it
into the txnList field (e.g., txnList = Just <mappedTxnList>), otherwise replace
the ambiguous comment with a clear comment explaining why txnList is
intentionally Nothing for the transaction-only webhook case.

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs`:
- Around line 329-330: Add a short comment above the Read instance for TxnDetail
explaining why readsPrec always returns []: clarify that the instance is a
deliberate pragmatic stub to satisfy typeclass constraints (instance Read
TxnDetail with readsPrec _ _ = []) because TxnDetail is too complex or not
intended to be parsed from strings, and note that parsing is unsupported and any
attempt to read should fail; reference the instance declaration (instance Read
TxnDetail) and the readsPrec implementation to locate where to add the comment.

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs`:
- Line 235: Remove the redundant explicit mapping "payment_rules" ->
"payment_rules" from the fieldLabelModifier map in CreateOrder.hs; locate the
Aeson options (the fieldLabelModifier function or the record-to-JSON mapping in
the CreateOrder module) and delete that identity entry so the fallback clause
(other -> other) handles it, leaving any other explicit mappings intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6466675e-deef-4669-84ff-7c9b9d32136e

📥 Commits

Reviewing files that changed from the base of the PR and between 1afc7a0 and b5f9eb5.

📒 Files selected for processing (7)
  • lib/mobility-core/src/Kernel/External/Payment/Interface.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/PaytmEDC.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs
  • lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs
  • lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs
  • lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs

Comment on lines +605 to +606
basket = req.basket,
paymentRules = req.paymentRules
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if PaytmEDC flow actually uses the paymentRules field
rg -n "paymentRules" lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/

# Check the PaytmEDC sale request body structure
ast-grep --pattern 'data PaytmEDCSaleRequestBody = PaytmEDCSaleRequestBody { $$$ }'

Repository: nammayatri/shared-kernel

Length of output: 1066


🏁 Script executed:

# Check the actual code at lines 605-606 in Interface.hs
cat -n lib/mobility-core/src/Kernel/External/Payment/Interface.hs | sed -n '595,620p'

Repository: nammayatri/shared-kernel

Length of output: 1462


🏁 Script executed:

# Check what CreateOrderReq is being used for PaytmEDC
rg -n "CreateOrderReq" lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/ -A 5

# Check if paymentRules is filtered or excluded for any provider
rg -n "paymentRules" lib/mobility-core/src/Kernel/External/Payment/ -B 3 -A 3

Repository: nammayatri/shared-kernel

Length of output: 3967


🏁 Script executed:

# Get the PaytmEDC Types file to understand all available request types
cat -n lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs

Repository: nammayatri/shared-kernel

Length of output: 15107


🏁 Script executed:

# Find PaytmEDCCreateOrderReq definition
rg -n "data PaytmEDCCreateOrderReq" lib/mobility-core/src/Kernel/External/Payment/ -A 20

# Check PaytmEDC implementation - how it converts the request
cat -n lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Impl.hs | head -100

Repository: nammayatri/shared-kernel

Length of output: 162


🏁 Script executed:

# Check if there's any handling of paymentRules in PaytmEDC flow
rg -n "paymentRules" lib/mobility-core/src/Kernel/External/Payment/Interface.hs -B 10 -A 3 | head -60

Repository: nammayatri/shared-kernel

Length of output: 1733


🏁 Script executed:

# Find PaytmEDCCreateOrderReq definition
rg -n "PaytmEDCCreateOrderReq" lib/mobility-core/src/Kernel/External/Payment/ -A 15

# Find PaytmEDC.createOrder implementation
rg -n "createOrder" lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/ -A 10

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# List all PaytmEDC files
find lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/ -type f -name "*.hs"

Repository: nammayatri/shared-kernel

Length of output: 326


🏁 Script executed:

# Find PaytmEDCCreateOrderReq - it might be in Interface/Types.hs
rg -n "PaytmEDCCreateOrderReq" lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs -A 20

# Check PaytmEDC Flow implementation
cat -n lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Flow.hs

Repository: nammayatri/shared-kernel

Length of output: 4392


🏁 Script executed:

# Search for PaytmEDCCreateOrderReq in Interface types
rg -n "PaytmEDCCreateOrderReq" lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs -B 2 -A 20

# Also search where createOrder is called from PaytmEDC module
rg -n "PaytmEDC.createOrder" lib/mobility-core/src/Kernel/External/Payment/ -B 3 -A 10

Repository: nammayatri/shared-kernel

Length of output: 2768


🏁 Script executed:

# Check the whole Interface.hs createPaymentOrder function around line 605
cat -n lib/mobility-core/src/Kernel/External/Payment/Interface.hs | sed -n '560,625p'

Repository: nammayatri/shared-kernel

Length of output: 3282


🏁 Script executed:

# Find PaytmEDC module with createOrder function
find lib/mobility-core/src/Kernel/External/Payment -name "*.hs" -type f | xargs grep -l "createOrder.*PaytmEDC" | head -5

# Check PaytmEDC module exports
rg -n "module.*PaytmEDC" lib/mobility-core/src/Kernel/External/Payment/ -A 30

Repository: nammayatri/shared-kernel

Length of output: 14348


🏁 Script executed:

# Search for PaytmEDC.createOrder definition
rg -n "createOrder.*::" lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/ -A 15

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Get the full PaytmEDC createOrder implementation
cat -n lib/mobility-core/src/Kernel/External/Payment/Interface/PaytmEDC.hs

Repository: nammayatri/shared-kernel

Length of output: 15638


Remove unused paymentRules field from PaytmEDC payment request.

The paymentRules field is passed to PaytmEDC's CreateOrderReq but is never used in the implementation. The PaytmEDC flow only extracts and sends a subset of fields to the actual API request (PaytmEDCSaleRequestBody), excluding paymentRules entirely. Unlike Juspay which actively converts this field, PaytmEDC silently ignores it. Remove it to avoid confusion and keep the request object focused on fields that are actually used.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Interface.hs` around lines 605
- 606, The PaytmEDC payment request construction includes an unused field
paymentRules (seen where CreateOrderReq is assembled with basket = req.basket,
paymentRules = req.paymentRules) but PaytmEDC only serializes a
PaytmEDCSaleRequestBody and never uses paymentRules; remove the paymentRules
assignment from the CreateOrderReq construction and any type/record fields
specific to PaytmEDC that reference paymentRules, update the
CreateOrderReq/PaytmEDC request type signatures and any callers to reflect the
removed field, and ensure PaytmEDCSaleRequestBody mapping continues to include
only the actual used fields (e.g., basket and other existing fields).

Comment on lines +180 to 185
paymentMode :: Maybe Text,
loyaltyInfo :: Maybe LoyaltyInfo,
txnDetails :: Maybe [TxnList]
}
deriving stock (Show, Eq, Generic)
deriving anyclass (ToJSON, FromJSON)
Copy link
Copy Markdown

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
# Check how PaytmEDCResponseBody derives JSON instances
rg -A5 "deriving anyclass.*FromJSON" lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs

# Check how LoyaltyInfo and TxnList derive JSON instances
rg -B5 -A10 "instance FromJSON LoyaltyInfo" lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs
rg -B5 -A10 "instance FromJSON TxnList" lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs

Repository: nammayatri/shared-kernel

Length of output: 2858


Fix JSON serialization mismatch between parent and nested types.

PaytmEDCResponseBody uses default ToJSON/FromJSON derivation (camelCase), but the nested LoyaltyInfo and TxnList types have explicit instances using jsonSnakeOptions (snake_case). When PaytmEDCResponseBody deserializes JSON with fields loyalty_info and txn_details, parsing will fail because the parent expects camelCase field names.

Add explicit FromJSON/ToJSON instances to PaytmEDCResponseBody using jsonSnakeOptions to match the nested types, or ensure the API response format aligns with the expected field naming convention.

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

In `@lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs` around lines
180 - 185, PaytmEDCResponseBody currently derives default ToJSON/FromJSON
(camelCase) while nested types LoyaltyInfo and TxnList use jsonSnakeOptions
(snake_case), causing deserialization mismatches; add explicit instance
declarations for FromJSON and ToJSON for PaytmEDCResponseBody using
jsonSnakeOptions (same options used by LoyaltyInfo and TxnList) so fields like
loyalty_info and txn_details parse correctly, or alternatively update
LoyaltyInfo/TxnList to match the parent — locate PaytmEDCResponseBody in
Types.hs and implement the jsonSnakeOptions-based instances to align names
across types.

Copy link
Copy Markdown

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/mobility-core/src/Kernel/External/Wallet/Interface.hs (1)

20-27: 🛠️ Refactor suggestion | 🟠 Major

Add the repo-preferred Prelude import explicitly.

This module is relying on transitive imports instead of bringing in Kernel.Prelude/EulerHS.Prelude directly, which is out of line with the repository standard for NoImplicitPrelude modules.

As per coding guidelines, All modules must import Kernel.Prelude or EulerHS.Prelude instead of the standard Prelude due to NoImplicitPrelude language pragma.

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

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface.hs` around lines 20 -
27, This module is using transitive Prelude symbols instead of importing the
repo-preferred prelude; update Kernel/External/Wallet/Interface.hs to explicitly
import the project prelude (e.g. add import Kernel.Prelude or import
EulerHS.Prelude at the top of the module) rather than relying on transitive
imports, and ensure functions/types used in this file (referenced in this module
like Payment, Juspay, WalletConfig, CoreMetrics, GenericError/InvalidRequest)
continue to resolve—remove any accidental dependency on standard Prelude symbols
and keep existing qualified imports as-is.
🧹 Nitpick comments (6)
lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs (2)

471-478: Remove commented-out code after migration is complete.

The old TxnDetail definition is commented out. Consider removing it once you've verified all downstream usages work correctly with the new expanded TxnDetail type.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs` around
lines 471 - 478, Remove the commented-out legacy TxnDetail block from Common.hs
now that the migration to the new expanded TxnDetail is complete; locate the
commented section containing the old TxnDetail definition (the block starting
with "data TxnDetail = TxnDetail" and ending with the deriving lines) and delete
it so the file contains only the current TxnDetail type and its instances,
ensuring no commented legacy definitions remain.

329-330: Stub Read instance always fails - verify this is intentional.

The Read TxnDetail instance returns [] for any input, meaning read will always fail. This appears to be a workaround because TxnList derives Read and contains Maybe TxnDetail. While acceptable for Maybe fields (they'll default to Nothing on parse failure in some contexts), consider documenting this behavior or adding a comment explaining why a full Read instance isn't provided.

📝 Suggested documentation
 instance Read TxnDetail where
+  -- Stub instance: TxnDetail has too many fields for meaningful string parsing.
+  -- Required because TxnList derives Read.
   readsPrec _ _ = []
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs` around
lines 329 - 330, The Read instance for TxnDetail currently always fails
(readsPrec _ _ = []) which makes read on TxnDetail unusable; either document
this intentional stub or implement a proper parser—locate the instance
declaration "instance Read TxnDetail" in Common.hs and either add a comment
explaining that TxnDetail is intentionally non-parsable (and why, e.g. relying
on TxnList's Maybe semantics) or replace the stub with a correct readsPrec
implementation that parses the textual representation of TxnDetail consistent
with its Show/derived form so that read and readsPrec behave correctly.
lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs (1)

355-362: Remove commented-out TxnDetail definition.

Similar to Juspay/Types/Common.hs, this commented-out local TxnDetail definition should be removed once migration is verified. The type is now correctly imported from Juspay.Types.

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

In `@lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs` around
lines 355 - 362, Remove the dead/commented TxnDetail declaration block: delete
the commented-out TxnDetail definition (the block starting with "data TxnDetail
= TxnDetail" and its deriving clauses) in Types.hs since TxnDetail is now
imported from Juspay.Types; ensure no other local references remain and rely on
the existing import of Juspay.Types for the TxnDetail type.
lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs (1)

136-143: Model the three headers as required in the API type.

The implementation treats all three headers as mandatory, but plain Header keeps them optional in the generated client and forces the extra Just plumbing. Servant supports Header' '[Required, Strict] for this exact case, which would make the type-level contract match the endpoint contract. (hackage.haskell.org)

🔧 Suggested tightening
 type LoyaltyInfoAPI =
   "loyalty"
     :> "programs"
-    :> Header "Authorization" Text
-    :> Header "X-MerchantId" Text
-    :> Header "x-tenant-id" Text
+    :> Header' '[Required, Strict] "Authorization" Text
+    :> Header' '[Required, Strict] "X-MerchantId" Text
+    :> Header' '[Required, Strict] "x-tenant-id" Text
     :> ReqBody '[JSON] LoyaltyInfoRequest
     :> Post '[JSON] LoyaltyInfoResponse
@@
 loyaltyInfo url authHeader merchantId tenantId req = do
   let proxy = Proxy `@LoyaltyInfoAPI`
-      eulerClient = Euler.client proxy (Just authHeader) (Just merchantId) (Just tenantId) req
+      eulerClient = Euler.client proxy authHeader merchantId tenantId req

Also applies to: 155-155

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

In `@lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs` around lines 136
- 143, The API type LoyaltyInfoAPI currently uses plain Header which makes
"Authorization", "X-MerchantId" and "x-tenant-id" optional; change each Header
to Header' '[Required, Strict] to mark them required and strict so the generated
client and type-level contract match the implementation; update the same pattern
for the other occurrence mentioned (the similar API type at the second location)
ensuring the three header symbols are replaced with Header' '[Required, Strict]
for Authorization, X-MerchantId and x-tenant-id.
lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs (1)

145-146: Omit absent request fields from the loyalty payload.

jsonSnakeOptions only changes fieldLabelModifier, so it still inherits Aeson's default omitNothingFields = False. That means order = Nothing will be sent as "order": null instead of being omitted, which is an avoidable interoperability risk for an outbound API request. (hackage.haskell.org)

💡 Minimal fix
+requestJsonOptions :: Options
+requestJsonOptions = jsonSnakeOptions {omitNothingFields = True}
+
 instance ToJSON LoyaltyInfoRequest where
-  toJSON = genericToJSON jsonSnakeOptions
+  toJSON = genericToJSON requestJsonOptions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs` around lines
145 - 146, The ToJSON instance for LoyaltyInfoRequest uses genericToJSON
jsonSnakeOptions which doesn't set omitNothingFields, so Nothing fields are
encoded as null; update the ToJSON instance to use an Aeson Options value
derived from jsonSnakeOptions with omitNothingFields = True (either by creating
a new options value like jsonSnakeOmitNothing = jsonSnakeOptions {
omitNothingFields = True } or by passing a modified record inline) and call
genericToJSON with that options value so absent request fields are omitted from
the payload; ensure the change targets the LoyaltyInfoRequest ToJSON instance
and reuses jsonSnakeOptions as the base.
lib/mobility-core/src/Kernel/External/Wallet/Interface.hs (1)

93-101: This top-level interface now leaks the Juspay-specific config type.

Every other wallet entry point in this module dispatches on PaymentServiceConfig, but loyaltyInfo now forces callers to know about Kernel.External.Wallet.Juspay.Config.LoyaltyCfg. I'd either route this through a common config sum as well, or keep it in the Juspay-specific interface until there is a provider-neutral abstraction.

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

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface.hs` around lines 93 -
101, The top-level loyaltyInfo function leaks the Juspay-specific
WalletConfig.LoyaltyCfg; change its API to accept the provider-agnostic
PaymentServiceConfig (the same sum used by other wallet entry points) and
dispatch to Juspay.loyaltyInfo only when the PaymentServiceConfig matches the
Juspay variant, or alternatively move this loyaltyInfo implementation into the
Juspay-specific module and keep the top-level signature provider-neutral; update
the loyaltyInfo type signature and body to pattern-match on PaymentServiceConfig
and call Juspay.loyaltyInfo with the extracted LoyaltyCfg when appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs`:
- Around line 30-31: The OpenAPI ToSchema instances are not using the same Aeson
field options, causing schema names to differ from serialized JSON; update each
ToSchema derivation to use openapi3's fromAesonOptions by converting your
existing Aeson Options (e.g., jsonSnakeOptions, walletProgramOptions,
burnOptionOptions, and any other custom Options defined in this file) into
SchemaOptions and pass those to the Generic-based ToSchema derivation (use
fromAesonOptions jsonSnakeOptions etc.) so generated schemas reflect the Aeson
fieldLabelModifier mappings (apply this change for the types referenced around
jsonSnakeOptions and at the other listed sections).

In `@lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs`:
- Around line 153-157: The current error handling in loyaltyInfo embeds the full
Servant error via show err which can leak headers/auth; change the lambda passed
to fromEitherM to pattern-match on Servant's ClientError (e.g. FailureResponse,
ConnectionError, DecodeFailure, InvalidContentTypeHeader,
WrongRequestBodyLength) and construct an InternalError that only includes safe
fields (for FailureResponse use responseStatusCode and a short/truncated
responseBody or a fixed message like "response body omitted"; for
ConnectionError include a sanitized exception message without request/headers).
Update the mapping so callAPI ... >>= fromEitherM (\err -> ...) builds this
redacted message (referencing ClientError, FailureResponse, responseStatusCode,
responseBody, loyaltyInfo, callAPI, fromEitherM, InternalError) instead of using
show err.

---

Outside diff comments:
In `@lib/mobility-core/src/Kernel/External/Wallet/Interface.hs`:
- Around line 20-27: This module is using transitive Prelude symbols instead of
importing the repo-preferred prelude; update Kernel/External/Wallet/Interface.hs
to explicitly import the project prelude (e.g. add import Kernel.Prelude or
import EulerHS.Prelude at the top of the module) rather than relying on
transitive imports, and ensure functions/types used in this file (referenced in
this module like Payment, Juspay, WalletConfig, CoreMetrics,
GenericError/InvalidRequest) continue to resolve—remove any accidental
dependency on standard Prelude symbols and keep existing qualified imports
as-is.

---

Nitpick comments:
In `@lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs`:
- Around line 355-362: Remove the dead/commented TxnDetail declaration block:
delete the commented-out TxnDetail definition (the block starting with "data
TxnDetail = TxnDetail" and its deriving clauses) in Types.hs since TxnDetail is
now imported from Juspay.Types; ensure no other local references remain and rely
on the existing import of Juspay.Types for the TxnDetail type.

In `@lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs`:
- Around line 471-478: Remove the commented-out legacy TxnDetail block from
Common.hs now that the migration to the new expanded TxnDetail is complete;
locate the commented section containing the old TxnDetail definition (the block
starting with "data TxnDetail = TxnDetail" and ending with the deriving lines)
and delete it so the file contains only the current TxnDetail type and its
instances, ensuring no commented legacy definitions remain.
- Around line 329-330: The Read instance for TxnDetail currently always fails
(readsPrec _ _ = []) which makes read on TxnDetail unusable; either document
this intentional stub or implement a proper parser—locate the instance
declaration "instance Read TxnDetail" in Common.hs and either add a comment
explaining that TxnDetail is intentionally non-parsable (and why, e.g. relying
on TxnList's Maybe semantics) or replace the stub with a correct readsPrec
implementation that parses the textual representation of TxnDetail consistent
with its Show/derived form so that read and readsPrec behave correctly.

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface.hs`:
- Around line 93-101: The top-level loyaltyInfo function leaks the
Juspay-specific WalletConfig.LoyaltyCfg; change its API to accept the
provider-agnostic PaymentServiceConfig (the same sum used by other wallet entry
points) and dispatch to Juspay.loyaltyInfo only when the PaymentServiceConfig
matches the Juspay variant, or alternatively move this loyaltyInfo
implementation into the Juspay-specific module and keep the top-level signature
provider-neutral; update the loyaltyInfo type signature and body to
pattern-match on PaymentServiceConfig and call Juspay.loyaltyInfo with the
extracted LoyaltyCfg when appropriate.

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs`:
- Around line 145-146: The ToJSON instance for LoyaltyInfoRequest uses
genericToJSON jsonSnakeOptions which doesn't set omitNothingFields, so Nothing
fields are encoded as null; update the ToJSON instance to use an Aeson Options
value derived from jsonSnakeOptions with omitNothingFields = True (either by
creating a new options value like jsonSnakeOmitNothing = jsonSnakeOptions {
omitNothingFields = True } or by passing a modified record inline) and call
genericToJSON with that options value so absent request fields are omitted from
the payload; ensure the change targets the LoyaltyInfoRequest ToJSON instance
and reuses jsonSnakeOptions as the base.

In `@lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs`:
- Around line 136-143: The API type LoyaltyInfoAPI currently uses plain Header
which makes "Authorization", "X-MerchantId" and "x-tenant-id" optional; change
each Header to Header' '[Required, Strict] to mark them required and strict so
the generated client and type-level contract match the implementation; update
the same pattern for the other occurrence mentioned (the similar API type at the
second location) ensuring the three header symbols are replaced with Header'
'[Required, Strict] for Authorization, X-MerchantId and x-tenant-id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 085e20d6-84be-4a75-ba39-6fdb090e9c9c

📥 Commits

Reviewing files that changed from the base of the PR and between b5f9eb5 and 68ae95b.

📒 Files selected for processing (12)
  • lib/mobility-core/src/Kernel/External/Payment/Interface.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/PaytmEDC.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs
  • lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/Common.hs
  • lib/mobility-core/src/Kernel/External/Payment/Juspay/Types/CreateOrder.hs
  • lib/mobility-core/src/Kernel/External/Payment/PaytmEDC/Types.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Interface.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Interface/Juspay.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Juspay/Config.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs
✅ Files skipped from review due to trivial changes (3)
  • lib/mobility-core/src/Kernel/External/Payment/Interface/PaytmEDC.hs
  • lib/mobility-core/src/Kernel/External/Payment/Interface.hs
  • lib/mobility-core/src/Kernel/External/Wallet/Juspay/Config.hs
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/mobility-core/src/Kernel/External/Payment/Interface/Juspay.hs

Comment on lines +30 to +31
jsonSnakeOptions :: Options
jsonSnakeOptions = defaultOptions {fieldLabelModifier = camelToSnakeCase}
Copy link
Copy Markdown

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:

# First, check if the file exists and examine its contents
wc -l "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 135


🏁 Script executed:

# Read the file to understand its structure, focusing on the import statements first
head -40 "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 1517


🏁 Script executed:

# Check the jsonSnakeOptions definition around lines 30-31
sed -n '25,35p' "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 415


🏁 Script executed:

# Look for ToSchema instances in the file
rg "ToSchema|SchemaOptions|fromAesonOptions" "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs" -n

Repository: nammayatri/shared-kernel

Length of output: 1894


🏁 Script executed:

# Check the custom Aeson options usage and field mappings
sed -n '135,160p' "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 815


🏁 Script executed:

# Check for any SchemaOptions or fromAesonOptions usage
rg "SchemaOptions|schemaOptions|fromAesonOptions" "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs" -n

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Look at more custom FromJSON/ToJSON instances around the mentioned lines
sed -n '140,160p' "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 664


🏁 Script executed:

# Check around lines 187-227
sed -n '187,227p' "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 1200


🏁 Script executed:

# Check around lines 320-345
sed -n '320,345p' "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs"

Repository: nammayatri/shared-kernel

Length of output: 745


🏁 Script executed:

# Check if openapi3 is imported or used in any way
rg "openapi3|OpenAPI|SchemaOptions" "lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs" -n

Repository: nammayatri/shared-kernel

Length of output: 50


Keep ToSchema aligned with custom Aeson field mappings.

Types throughout this file use custom Aeson options (jsonSnakeOptions, walletProgramOptions, burnOptionOptions, etc.) to remap JSON field names (e.g., customerIdid, id_id, type_type, camelCasesnake_case), but the generic ToSchema derivations do not apply these same options. The OpenAPI schema will describe Haskell field names instead of the actual JSON keys, creating a mismatch. Use openapi3's fromAesonOptions to wire your Aeson options into SchemaOptions for ToSchema derivation.

Applies to: lines 30–31, 140–158, 187–227, 320–345, 398–417, 445–479

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

In `@lib/mobility-core/src/Kernel/External/Wallet/Interface/Types.hs` around lines
30 - 31, The OpenAPI ToSchema instances are not using the same Aeson field
options, causing schema names to differ from serialized JSON; update each
ToSchema derivation to use openapi3's fromAesonOptions by converting your
existing Aeson Options (e.g., jsonSnakeOptions, walletProgramOptions,
burnOptionOptions, and any other custom Options defined in this file) into
SchemaOptions and pass those to the Generic-based ToSchema derivation (use
fromAesonOptions jsonSnakeOptions etc.) so generated schemas reflect the Aeson
fieldLabelModifier mappings (apply this change for the types referenced around
jsonSnakeOptions and at the other listed sections).

Comment on lines +153 to +157
loyaltyInfo url authHeader merchantId tenantId req = do
let proxy = Proxy @LoyaltyInfoAPI
eulerClient = Euler.client proxy (Just authHeader) (Just merchantId) (Just tenantId) req
callAPI url eulerClient "loyalty-info" proxy
>>= fromEitherM (\err -> InternalError $ "Failed to call loyalty info API: " <> show err)
Copy link
Copy Markdown

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
if [ -f "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" ]; then
  echo "=== File exists, reading lines 150-160 ==="
  sed -n '150,160p' "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" | cat -n
else
  echo "File not found, listing directory:"
  ls -la lib/mobility-core/src/Kernel/External/Wallet/Juspay/ 2>/dev/null || echo "Directory not found"
fi

Repository: nammayatri/shared-kernel

Length of output: 552


🏁 Script executed:

# Search for similar patterns in the codebase with fromEitherM and show err
rg "fromEitherM.*show err" --type hs -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 15297


🏁 Script executed:

# Check the imports in the Flow.hs file to understand what's being used
head -30 "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" | cat -n

Repository: nammayatri/shared-kernel

Length of output: 1449


🏁 Script executed:

# Look for how ClientError is being imported and used
rg "ClientError" "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Find callAPI definition
rg "callAPI ::|callAPI\s*::" --type hs -A 5

Repository: nammayatri/shared-kernel

Length of output: 993


🏁 Script executed:

# Find LoyaltyInfoAPI type definition
sed -n '136,160p' "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" | cat -n

Repository: nammayatri/shared-kernel

Length of output: 967


🏁 Script executed:

# Search for where authHeader is created or used in loyaltyInfo context
rg "loyaltyInfo|authHeader" "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" -B 3 -A 3

Repository: nammayatri/shared-kernel

Length of output: 652


🏁 Script executed:

# Check the types used for auth in Juspay APIs
rg "mkBasicAuthData|BasicAuthData" "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Check where loyaltyInfo is called to understand how authHeader is prepared
rg "loyaltyInfo\s*\(" --type hs -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Look for any sanitization or redaction of auth headers
rg "show|Show.*ClientError|redact|sanitize" "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" -B 2 -A 2 | head -40

Repository: nammayatri/shared-kernel

Length of output: 1755


🏁 Script executed:

# Check Servant version in cabal or other dependency files
fd -e cabal -e yaml -o lock | xargs grep -l "servant-client" 2>/dev/null | head -5

Repository: nammayatri/shared-kernel

Length of output: 195


🏁 Script executed:

# Look at the callAPI' implementation to understand what error type is returned
sed -n '1,100p' "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" | cat -n

Repository: nammayatri/shared-kernel

Length of output: 4316


🏁 Script executed:

# Search for how loyaltyInfo is called - where does authHeader come from?
rg "loyaltyInfo.*=" --type hs -B 5 -A 2

Repository: nammayatri/shared-kernel

Length of output: 5655


🏁 Script executed:

# Check if there's any credential/key handling in the Wallet module
rg "decrypt|BasicAuth|Authorization" "lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs" -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 199


🏁 Script executed:

# Look at Servant ClientError Show instance behavior - check what it includes
cat "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" | sed -n '1,60p'

Repository: nammayatri/shared-kernel

Length of output: 2428


🏁 Script executed:

# Search for the actual call site of loyaltyInfo to understand authHeader's origin
rg "loyaltyInfo" --type hs --type hsc -B 3 -A 3 | head -50

Repository: nammayatri/shared-kernel

Length of output: 95


🏁 Script executed:

# Check if there's any redaction/sanitization of error logging for ClientError
rg "logError|logWarning" "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" -B 3 -A 3 | head -30

Repository: nammayatri/shared-kernel

Length of output: 1204


🏁 Script executed:

# Look at the full loyaltyInfo setup in Juspay.hs to confirm authHeader is the decrypted credential
cat "lib/mobility-core/src/Kernel/External/Wallet/Interface/Juspay.hs" | sed -n '1,60p'

Repository: nammayatri/shared-kernel

Length of output: 2135


🏁 Script executed:

# Check if there are any header redaction utilities in the codebase
rg "sanitiz|redact|scrub.*[Hh]eader" --type hs

Repository: nammayatri/shared-kernel

Length of output: 1412


🏁 Script executed:

# Find the exact lines where authHeader is constructed in Juspay.hs
rg "authHeader.*Basic|Basic.*apiKey" "lib/mobility-core/src/Kernel/External/Wallet/Interface/Juspay.hs" -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 304


🏁 Script executed:

# Find the cabal file or dependency declaration to see Servant version
find . -name "*.cabal" -o -name "cabal.project" | head -5

Repository: nammayatri/shared-kernel

Length of output: 216


🏁 Script executed:

# Check what version of servant-client is being used
rg "servant-client" "cabal.project" -A 1 -B 1 2>/dev/null | head -20

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Look for any existing mitigation or header filtering in the error handling
rg "ClientError" "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" -B 5 -A 5 | head -60

Repository: nammayatri/shared-kernel

Length of output: 801


🏁 Script executed:

# Search for imports of ClientError to understand where it comes from
rg "import.*ClientError|from.*ClientError" "lib/mobility-core/src/Kernel" --type hs

Repository: nammayatri/shared-kernel

Length of output: 2067


🏁 Script executed:

# Let's examine the exact Servant ClientError definition to confirm it includes request headers
grep -r "data ClientError" --type hs -A 10

Repository: nammayatri/shared-kernel

Length of output: 185


🏁 Script executed:

# Check if there's any existing error filtering/redaction for secrets in fromEitherM
rg "fromEitherM" "lib/mobility-core/src/Kernel/Utils/Common.hs" -B 3 -A 5

Repository: nammayatri/shared-kernel

Length of output: 50


🏁 Script executed:

# Verify the Servant version in the dependencies
cat "lib/mobility-core/mobility-core.cabal" | grep -i "servant" | head -10

Repository: nammayatri/shared-kernel

Length of output: 414


🏁 Script executed:

# Get the full dependency list from cabal file
cat "lib/mobility-core/mobility-core.cabal" | grep -A 200 "build-depends:" | grep -i "servant"

Repository: nammayatri/shared-kernel

Length of output: 443


🏁 Script executed:

# Check what ClientError contains by looking at imports and uses
rg "FailureResponse|ConnectionError|DecodeFailure" "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs" -B 2 -A 2

Repository: nammayatri/shared-kernel

Length of output: 1004


🏁 Script executed:

# Look at how ClientError is pattern matched to understand its structure
rg "ClientError\s*\(" --type hs -A 2 | head -30

Repository: nammayatri/shared-kernel

Length of output: 1561


🏁 Script executed:

# Check if the issue mentions redacting errors elsewhere - look at error handling in callAPI
sed -n '140,180p' "lib/mobility-core/src/Kernel/Utils/Servant/Client.hs"

Repository: nammayatri/shared-kernel

Length of output: 1565


Redact the Servant error before embedding it in InternalError.

When callAPI returns a ClientError from a failed request, its Show instance includes the full HTTP request including headers. Since authHeader carries the decrypted API key as a Base64-encoded Basic authentication credential, calling show err will serialize this secret into the error message and expose it via logError logging and telemetry systems.

Instead of show err, extract only the status code and safe error details. Consider using Servant's FailureResponse pattern to access the status selectively without serializing headers.

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

In `@lib/mobility-core/src/Kernel/External/Wallet/Juspay/Flow.hs` around lines 153
- 157, The current error handling in loyaltyInfo embeds the full Servant error
via show err which can leak headers/auth; change the lambda passed to
fromEitherM to pattern-match on Servant's ClientError (e.g. FailureResponse,
ConnectionError, DecodeFailure, InvalidContentTypeHeader,
WrongRequestBodyLength) and construct an InternalError that only includes safe
fields (for FailureResponse use responseStatusCode and a short/truncated
responseBody or a fixed message like "response body omitted"; for
ConnectionError include a sanitized exception message without request/headers).
Update the mapping so callAPI ... >>= fromEitherM (\err -> ...) builds this
redacted message (referencing ClientError, FailureResponse, responseStatusCode,
responseBody, loyaltyInfo, callAPI, fromEitherM, InternalError) instead of using
show err.

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