Skip to content

[AI] Add confirmation-required field to intent validation API#742

Merged
wheval merged 2 commits into
ancore-org:mainfrom
olaleyeolajide81-sketch:Add-confirmation-required-field-to-intent-validation-API
Jun 4, 2026
Merged

[AI] Add confirmation-required field to intent validation API#742
wheval merged 2 commits into
ancore-org:mainfrom
olaleyeolajide81-sketch:Add-confirmation-required-field-to-intent-validation-API

Conversation

@olaleyeolajide81-sketch

@olaleyeolajide81-sketch olaleyeolajide81-sketch commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Extended paymentIntentSchema to include requiresConfirmation field
  • Added logic to flag high-value payments (>100 USDC or >1000 XLM) as requiring confirmation
  • Updated /v1/intents/validate endpoint to return confirmation metadata in response
  • Added comprehensive tests for the new confirmation field

Changes

  • services/ai-agent/src/schemas/intent.ts: Added requiresConfirmation boolean field
  • services/ai-agent/src/server.ts: Added requiresConfirmation helper function and updated validation endpoint
  • services/ai-agent/src/server.test.ts: Added test suite for /v1/intents/validate endpoint

Test plan

  • Added 5 new test cases for the /v1/intents/validate endpoint
  • Tests verify confirmation logic for both USDC and XLM assets
  • Tests verify proper error handling for invalid inputs

Closes #682

Generated with Devin (https://cli.devin.ai/docs)

Summary by CodeRabbit

  • New Features
    • Added confirmation requirement for certain payment transactions based on asset type and transaction amount. Transactions exceeding 100 units of USDC or 1000 units of other assets now require additional confirmation before processing.

)

- Extended paymentIntentSchema to include requiresConfirmation field
- Added logic to flag high-value payments (>100 USDC or >1000 XLM) as requiring confirmation
- Updated /v1/intents/validate endpoint to return confirmation metadata
- Added comprehensive tests for the new confirmation field

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b37b2c58-ff51-4c37-81dc-a9851e9c8007

📥 Commits

Reviewing files that changed from the base of the PR and between 8c1bd4a and efea2d1.

📒 Files selected for processing (1)
  • services/ai-agent/src/server.ts
💤 Files with no reviewable changes (1)
  • services/ai-agent/src/server.ts

📝 Walkthrough

Walkthrough

A new local helper function requiresConfirmation(intent) was added to evaluate payment intents. It parses intent.amount and applies asset-dependent thresholds—greater than 100 for USDC, greater than 1000 for other assets—returning false for non-payment intents.

Changes

Payment Intent Confirmation Logic

Layer / File(s) Summary
Confirmation requirement helper
services/ai-agent/src/server.ts
Introduces a local requiresConfirmation helper that determines confirmation necessity by comparing payment intent amounts against asset-specific thresholds (USDC: >100, others: >1000).

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

  • ancore-org/ancore#717: Both PRs implement/extend the "intent confirmation" behavior by introducing/using requiresConfirmation logic tied to payment intent amounts and thresholds in the ai-agent server layer.
  • ancore-org/ancore#706: Both PRs modify services/ai-agent/src/server.ts to add payment-intent logic based on intent.amount and asset fields.

Poem

🐰 A helper hops in to check the pay,
USDC past 100, others at one-zero-oh-oh,
Confirmation flags rise or fall away,
Simple thresholds guide the flow. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: adding a confirmation-required field to the intent validation API, which aligns with the core objective of the PR.
Linked Issues check ✅ Passed The code changes implement the core requirements from issue #682: extending the payment intent schema with confirmation logic and flagging high-value payments (>100 USDC or >1000 other assets).
Out of Scope Changes check ✅ Passed Only a local helper function was added to server.ts for confirmation logic; all changes remain within the scope of extending intent validation with confirmation requirements as specified in issue #682.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
services/ai-agent/src/server.ts (1)

12-14: ⚡ Quick win

Handle potential NaN from parseFloat.

If intent.amount contains a malformed string that passes the regex but fails to parse (edge case), parseFloat returns NaN, and NaN > threshold is always false. While the schema regex should prevent this, defensive coding is safer if the function is reused.

🛡️ Proposed defensive fix
   const amount = parseFloat(intent.amount);
+  if (isNaN(amount)) {
+    return false;
+  }
   const threshold = intent.asset === 'USDC' ? 100 : 1000;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/ai-agent/src/server.ts` around lines 12 - 14, The current logic uses
parseFloat(intent.amount) and compares to threshold but doesn't handle
parseFloat returning NaN; update the code around parseFloat(intent.amount)
(variables: amount, threshold, intent.amount) to detect NaN
(Number.isNaN(amount)) and handle it defensively—either throw a clear error or
return false (and optionally log) before doing amount > threshold so malformed
amounts never silently pass/fail due to NaN behavior.
services/ai-agent/src/server.test.ts (1)

63-106: ⚡ Quick win

Consider adding boundary condition tests.

The test suite covers amounts above and below thresholds but doesn't test exact boundary values (100 USDC, 1000 XLM). Since the requirement is "greater than" (not "greater than or equal to"), adding tests for exactly 100 USDC and exactly 1000 XLM would verify the boundary behavior:

💡 Suggested additional test cases
it('returns 200 with requiresConfirmation=false for exactly 100 USDC', async () => {
  const res = await request(app)
    .post('/v1/intents/validate')
    .send({
      type: 'payment',
      amount: '100',
      asset: 'USDC',
      destination: 'GABC123',
    });
  expect(res.status).toBe(200);
  expect(res.body.requiresConfirmation).toBe(false);
});

it('returns 200 with requiresConfirmation=false for exactly 1000 XLM', async () => {
  const res = await request(app)
    .post('/v1/intents/validate')
    .send({
      type: 'payment',
      amount: '1000',
      asset: 'XLM',
      destination: 'GABC123',
    });
  expect(res.status).toBe(200);
  expect(res.body.requiresConfirmation).toBe(false);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/ai-agent/src/server.test.ts` around lines 63 - 106, Add two boundary
tests in services/ai-agent/src/server.test.ts that POST to /v1/intents/validate
with amount '100' for asset 'USDC' and amount '1000' for asset 'XLM' to assert
status 200 and requiresConfirmation is false; create tests similar to the
existing cases (e.g., the tests named "returns 200 with valid payment intent
below threshold" and the above-threshold tests) so they follow the same
structure and assert res.body.valid === true and res.body.intent.type ===
'payment' while specifically checking requiresConfirmation === false for the
exact boundary values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@services/ai-agent/src/schemas/intent.ts`:
- Line 11: The schema's requiresConfirmation boolean default conflicts with the
server-computed top-level requiresConfirmation; remove the requiresConfirmation
field from the intent Zod schema (delete the requiresConfirmation:
z.boolean().default(false) entry in services/ai-agent/src/schemas/intent.ts) so
the server-only computed value remains the single source of truth, and leave
server.ts's computation/response logic (the top-level requiresConfirmation added
to the response) unchanged; alternatively, if you prefer schema-owned values,
adjust server.ts to assign the computed value into
parsed.data.requiresConfirmation before returning, but default action: remove
the schema field.

In `@services/ai-agent/src/server.ts`:
- Line 10: The requiresConfirmation function currently types its parameter as
any; change its signature to accept intent: Intent and add (or ensure) an import
for Intent from "./schemas/intent" so the parameter uses the proper Intent type;
update any internal usages that rely on the previous loose typing if necessary
to satisfy the new type and ensure exports/imports remain consistent (target
function: requiresConfirmation).

---

Nitpick comments:
In `@services/ai-agent/src/server.test.ts`:
- Around line 63-106: Add two boundary tests in
services/ai-agent/src/server.test.ts that POST to /v1/intents/validate with
amount '100' for asset 'USDC' and amount '1000' for asset 'XLM' to assert status
200 and requiresConfirmation is false; create tests similar to the existing
cases (e.g., the tests named "returns 200 with valid payment intent below
threshold" and the above-threshold tests) so they follow the same structure and
assert res.body.valid === true and res.body.intent.type === 'payment' while
specifically checking requiresConfirmation === false for the exact boundary
values.

In `@services/ai-agent/src/server.ts`:
- Around line 12-14: The current logic uses parseFloat(intent.amount) and
compares to threshold but doesn't handle parseFloat returning NaN; update the
code around parseFloat(intent.amount) (variables: amount, threshold,
intent.amount) to detect NaN (Number.isNaN(amount)) and handle it
defensively—either throw a clear error or return false (and optionally log)
before doing amount > threshold so malformed amounts never silently pass/fail
due to NaN behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 571998c2-f835-4a42-aff1-62307c775798

📥 Commits

Reviewing files that changed from the base of the PR and between 2b6ed63 and 8c1bd4a.

📒 Files selected for processing (3)
  • services/ai-agent/src/schemas/intent.ts
  • services/ai-agent/src/server.test.ts
  • services/ai-agent/src/server.ts

Comment thread services/ai-agent/src/schemas/intent.ts Outdated
amount: z.string().regex(/^\d+(\.\d+)?$/, 'Invalid amount format'),
asset: z.enum(['XLM', 'USDC']),
destination: z.string().min(1, 'Destination is required'),
requiresConfirmation: z.boolean().default(false),

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 | ⚖️ Poor tradeoff

Schema field conflicts with server-computed value.

The schema defines requiresConfirmation with a default, but server.ts computes this value dynamically and places it at the response root level (not mutating intent.requiresConfirmation). This creates two separate fields:

  • intent.requiresConfirmation — from the schema default (always false unless a client sends true)
  • Top-level requiresConfirmation — computed by the server based on thresholds

This is confusing and creates inconsistent state. Consider one of these fixes:

Option A (recommended based on current server.ts implementation): Remove requiresConfirmation from the schema entirely, since it's computed server-side only:

📐 Proposed fix: Remove from schema
 export const paymentIntentSchema = z.object({
   type: z.literal('payment'),
   amount: z.string().regex(/^\d+(\.\d+)?$/, 'Invalid amount format'),
   asset: z.enum(['XLM', 'USDC']),
   destination: z.string().min(1, 'Destination is required'),
-  requiresConfirmation: z.boolean().default(false),
 });

Option B: Keep the schema field and have server.ts mutate it instead of adding a separate response field. This would require changing server.ts to:

parsed.data.requiresConfirmation = requiresConfirmation(parsed.data);
return res.status(200).json({ valid: true, intent: parsed.data });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/ai-agent/src/schemas/intent.ts` at line 11, The schema's
requiresConfirmation boolean default conflicts with the server-computed
top-level requiresConfirmation; remove the requiresConfirmation field from the
intent Zod schema (delete the requiresConfirmation: z.boolean().default(false)
entry in services/ai-agent/src/schemas/intent.ts) so the server-only computed
value remains the single source of truth, and leave server.ts's
computation/response logic (the top-level requiresConfirmation added to the
response) unchanged; alternatively, if you prefer schema-owned values, adjust
server.ts to assign the computed value into parsed.data.requiresConfirmation
before returning, but default action: remove the schema field.

* Determines if a payment intent requires confirmation based on amount.
* High-value payments (e.g., >100 USDC or >1000 XLM) require confirmation.
*/
function requiresConfirmation(intent: any): boolean {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Replace any type with proper type annotation.

The intent parameter should be typed as Intent (imported from ./schemas/intent) to provide type safety and better IDE support.

🔧 Proposed fix
-function requiresConfirmation(intent: any): boolean {
+function requiresConfirmation(intent: Intent): boolean {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/ai-agent/src/server.ts` at line 10, The requiresConfirmation
function currently types its parameter as any; change its signature to accept
intent: Intent and add (or ensure) an import for Intent from "./schemas/intent"
so the parameter uses the proper Intent type; update any internal usages that
rely on the previous loose typing if necessary to satisfy the new type and
ensure exports/imports remain consistent (target function:
requiresConfirmation).

@wheval wheval merged commit 1748488 into ancore-org:main Jun 4, 2026
3 of 6 checks passed
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.

[AI] Add confirmation-required field to intent validation API

2 participants