Add opt-in AURA trust-check adapter (integrations/aura)#10
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThis PR adds a complete AURA trust-check adapter to the PayBot SDK: a read-only, opt-in reputation gate that runs before settlement. The module exports ChangesAURA Trust-Check Adapter
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
…rations/aura/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json)
There was a problem hiding this comment.
Code Review
This pull request introduces the AURA trust-check adapter, a zero-dependency TypeScript integration for gating settlements based on counterparty reputation. The implementation includes core adapter logic, comprehensive offline tests, a threat model, and documentation. Review feedback focuses on refining the failOpen logic to better handle service unreachability, ensuring the ok property consistently reflects default gating behavior, and improving the clarity and completeness of documentation code examples by addressing missing imports and undefined variables.
| const allow = opts.allow ?? DEFAULT_ALLOW; | ||
| const v = await auraVerdict(did, opts); | ||
| if (allow.includes(v.verdict)) return v; | ||
| if (opts.failOpen && v.verdict === 'unknown' && !v.hasHistory) return v; |
There was a problem hiding this comment.
The current logic for failOpen (opts.failOpen && v.verdict === 'unknown' && !v.hasHistory) might be too broad. It allows a pass not only when the AURA service is unreachable, but also for any 'unknown' verdict where hasHistory is false (like a 'ghost' DID that is known to AURA but has no history). The documentation suggests failOpen should only apply to unreachable cases.
To make this more precise, I suggest adding a dedicated flag to the AuraVerdict object to indicate unreachability. This would make the failOpen logic more robust and aligned with its documented purpose.
This would require the following changes:
- Add
unreachable?: boolean;to theAuraVerdictinterface. - Set
unreachable: falseintoVerdictandunreachable: truein theunreachablehelper function. - Update this line to check
v.unreachableas shown in the suggestion.
| if (opts.failOpen && v.verdict === 'unknown' && !v.hasHistory) return v; | |
| if (opts.failOpen && v.unreachable) return v; |
| import { PayBotClient } from 'paybot-sdk'; | ||
| import { beforeSettle, AuraUntrusted } from './integrations/aura'; | ||
|
|
||
| const client = new PayBotClient(config); | ||
|
|
||
| async function payChecked(counterpartyDid: string, req: PaymentRequest) { |
There was a problem hiding this comment.
The code example in this section has a couple of issues that make it incomplete and potentially confusing for users:
- The
PaymentRequesttype is used inpayCheckedbut is not imported. - The
configobject used to initializePayBotClientis not defined.
To make the example self-contained and easier to follow, please add the missing import and a placeholder for the config object.
| import { PayBotClient } from 'paybot-sdk'; | |
| import { beforeSettle, AuraUntrusted } from './integrations/aura'; | |
| const client = new PayBotClient(config); | |
| async function payChecked(counterpartyDid: string, req: PaymentRequest) { | |
| import { PayBotClient, type PaymentRequest } from 'paybot-sdk'; | |
| import { beforeSettle, AuraUntrusted } from './integrations/aura'; | |
| // Replace with your actual PayBotClient configuration | |
| const config = { apiKey: '...', botId: '...' }; | |
| const client = new PayBotClient(config); | |
| async function payChecked(counterpartyDid: string, req: PaymentRequest) { |
| console.log(v.reason, v.score, v.ok); | ||
|
|
||
| // v.dimensions tells you *which* axis is weak, not just the aggregate: | ||
| if ((v.dimensions?.financial_integrity ?? 1) < 0.4) requireManualReview(); |
There was a problem hiding this comment.
The function requireManualReview() is not defined in this example, which might confuse readers. To improve clarity, please add a comment to indicate that this is a placeholder for the user's own policy logic.
| if ((v.dimensions?.financial_integrity ?? 1) < 0.4) requireManualReview(); | |
| if ((v.dimensions?.financial_integrity ?? 1) < 0.4) requireManualReview(); // Example: your custom policy logic |
| verdict, | ||
| reason: String(body.reason ?? ''), | ||
| score: typeof body.score === 'number' ? body.score : null, | ||
| ok: verdict === 'trusted' || verdict === 'caution', |
There was a problem hiding this comment.
There's a potential for confusion with the ok property. It is true only for 'trusted' and 'caution' verdicts, but the beforeSettle function's default behavior also allows 'new' verdicts. This inconsistency might lead developers to mistakenly believe that v.ok reflects the outcome of beforeSettle.
To improve clarity and consistency, consider aligning the ok property with the default gate behavior by also including 'new'. This would make the ok flag a more reliable indicator of the default gate's pass/fail status.
If you apply this change, please also update the ok column for the new verdict in integrations/aura/README.md.
| ok: verdict === 'trusted' || verdict === 'caution', | |
| ok: ['trusted', 'caution', 'new'].includes(verdict), |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
integrations/aura/adapter.test.ts (1)
122-125: ⚡ Quick winAdd a regression test:
failOpenmust not allow reachableunknownCurrent coverage only verifies transport failure. Add a case where AURA is reachable and returns
unknown(e.g.,did:aura:ghost-bot) withfailOpen: true, and assert rejection withAuraUntrusted.Suggested test addition
describe('network failure', () => { @@ it('gate passes on unreachable when failOpen', async () => { const v = await beforeSettle('did:aura:trusted-bot', { failOpen: true, fetchImpl: failFetch }); expect(v.verdict).toBe('unknown'); }); + + it('failOpen does not pass a reachable unknown verdict', async () => { + await expect( + beforeSettle('did:aura:ghost-bot', { failOpen: true, fetchImpl: okFetch }), + ).rejects.toBeInstanceOf(AuraUntrusted); + }); });🤖 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 `@integrations/aura/adapter.test.ts` around lines 122 - 125, Add a regression test that verifies failOpen does NOT convert a reachable AURA "unknown" response into a pass: call the same helper used elsewhere (beforeSettle) with a subject that AURA will respond to as unknown (e.g., 'did:aura:ghost-bot') and options including failOpen: true and a fetchImpl that returns an "unknown" response; assert that the call rejects with AuraUntrusted (use expect(...).rejects.toThrow(AuraUntrusted) or equivalent). Target the test in integrations/aura/adapter.test.ts alongside the existing unreachable failure test and reference beforeSettle and AuraUntrusted so the test fails if behavior regresses.integrations/aura/THREAT_MODEL.md (1)
43-52: 💤 Low valueOptional: Add language hint to fenced code block.
The fenced code block at line 43 lacks a language specifier, triggering a markdown linter warning. While the ASCII diagram renders fine, adding a language hint improves markdown validity.
♻️ Proposed fix
## Trust boundary summary -``` +```text PayBot host --(DID only, HTTPS GET)--> AURA /check --> verdict🤖 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 `@integrations/aura/THREAT_MODEL.md` around lines 43 - 52, The fenced ASCII diagram in THREAT_MODEL.md is missing a language hint; update the triple-backtick fence around the diagram (the block containing "PayBot host --(DID only, HTTPS GET)--> AURA /check --> verdict") to include a language specifier such as "text" (i.e. change ``` to ```text) so the markdown linter stops warning while keeping the content unchanged.
🤖 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 `@integrations/aura/adapter.ts`:
- Around line 150-151: The current check allows opts.failOpen to let any v with
verdict === 'unknown' and no history pass, including valid reachable AURA
"unknown" responses; restrict this to only transport-level failures by changing
the condition to require a transport failure indicator (e.g., v.transportFailure
|| v.error || similar flag populated when the AURA call failed to reach the
service) in addition to opts.failOpen, v.verdict === 'unknown' and
!v.hasHistory, and otherwise throw new AuraUntrusted(v); update the code that
builds v if needed to set that transport-failure flag so the adapter only fails
open on transport errors.
In `@integrations/aura/README.md`:
- Around line 17-40: The README uses a relative import for beforeSettle and
AuraUntrusted from './integrations/aura' which isn't exposed by package.json, so
consumers cannot import those symbols; fix by either adding a subpath export for
"./integrations/aura" in package.json pointing to
dist/integrations/aura/index.{js,d.ts}, or re-export beforeSettle and
AuraUntrusted from the package's main entry (index.ts) so users can import them
from 'paybot-sdk', or update the README example to import from the actual public
path your package exposes; ensure the referenced symbols beforeSettle and
AuraUntrusted are exported where you add the subpath or re-export.
---
Nitpick comments:
In `@integrations/aura/adapter.test.ts`:
- Around line 122-125: Add a regression test that verifies failOpen does NOT
convert a reachable AURA "unknown" response into a pass: call the same helper
used elsewhere (beforeSettle) with a subject that AURA will respond to as
unknown (e.g., 'did:aura:ghost-bot') and options including failOpen: true and a
fetchImpl that returns an "unknown" response; assert that the call rejects with
AuraUntrusted (use expect(...).rejects.toThrow(AuraUntrusted) or equivalent).
Target the test in integrations/aura/adapter.test.ts alongside the existing
unreachable failure test and reference beforeSettle and AuraUntrusted so the
test fails if behavior regresses.
In `@integrations/aura/THREAT_MODEL.md`:
- Around line 43-52: The fenced ASCII diagram in THREAT_MODEL.md is missing a
language hint; update the triple-backtick fence around the diagram (the block
containing "PayBot host --(DID only, HTTPS GET)--> AURA /check --> verdict") to
include a language specifier such as "text" (i.e. change ``` to ```text) so the
markdown linter stops warning while keeping the content unchanged.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f1192a76-e834-4ef9-bae1-99a571457255
⛔ Files ignored due to path filters (1)
integrations/aura/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.jsonis excluded by!**/node_modules/**
📒 Files selected for processing (6)
integrations/aura/README.mdintegrations/aura/THREAT_MODEL.mdintegrations/aura/adapter.test.tsintegrations/aura/adapter.tsintegrations/aura/index.tsintegrations/aura/vitest.config.ts
| ```ts | ||
| import { PayBotClient } from 'paybot-sdk'; | ||
| import { beforeSettle, AuraUntrusted } from './integrations/aura'; | ||
|
|
||
| const client = new PayBotClient(config); | ||
|
|
||
| async function payChecked(counterpartyDid: string, req: PaymentRequest) { | ||
| try { | ||
| await beforeSettle(counterpartyDid); // rejects high_risk + unknown | ||
| } catch (e) { | ||
| if (e instanceof AuraUntrusted) { | ||
| console.warn('blocked:', e.message); // your policy decides | ||
| return; | ||
| } | ||
| throw e; | ||
| } | ||
| return client.pay(req); // existing flow, unchanged | ||
| } | ||
| ``` | ||
|
|
||
| `payTo` in a `PaymentRequest` is a wallet address; the AURA DID is the | ||
| counterparty's portable identity, supplied by your own mapping. The gate keys | ||
| on that DID — it composes cleanly with PayBot's existing `TRUST_VIOLATION` | ||
| error model as a *pre-flight* reputation axis. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if package.json has subpath exports configured for integrations/aura
if [ -f package.json ]; then
echo "=== Checking package.json exports configuration ==="
jq -r '.exports // "No exports field"' package.json
else
echo "No package.json found at root"
fi
# Check for any existing integration imports in the codebase
echo -e "\n=== Searching for existing integration import patterns ==="
rg -n --type=ts "from ['\"].*integrations/" -C 2 || echo "No existing integration imports found"Repository: RBKunnela/paybot-sdk
Length of output: 570
Fix import path: package.json lacks subpath exports for the documented example.
The README example (line 19) shows import { beforeSettle, AuraUntrusted } from './integrations/aura', but package.json currently exports only the root entry point. SDK consumers cannot use the relative import path as documented.
Either:
- Add subpath export to package.json:
"./integrations/aura": { "import": "./dist/integrations/aura/index.js", "types": "./dist/integrations/aura/index.d.ts" } - Or re-export from the main index.ts so users import from
'paybot-sdk' - Or update the example to match the actual consumable import path
Confirm which pattern aligns with your SDK's public API design.
🤖 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 `@integrations/aura/README.md` around lines 17 - 40, The README uses a relative
import for beforeSettle and AuraUntrusted from './integrations/aura' which isn't
exposed by package.json, so consumers cannot import those symbols; fix by either
adding a subpath export for "./integrations/aura" in package.json pointing to
dist/integrations/aura/index.{js,d.ts}, or re-export beforeSettle and
AuraUntrusted from the package's main entry (index.ts) so users can import them
from 'paybot-sdk', or update the README example to import from the actual public
path your package exposes; ensure the referenced symbols beforeSettle and
AuraUntrusted are exported where you add the subpath or re-export.
|
Thanks @coderabbitai @gemini-code-assist — good catch on |
|
Thanks for the update, @luisllaver. The distinction between transport failures and reachable |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 16584
The test coverage hits both One small doc inconsistency: the README still says "17 tests" at the bottom, but you're now at 19. Worth a one-line fix before merge. Everything else looks clean — the |
Opt-in, read-only AURA trust-check adapter — picking up the Founding Contributors invite (#3).
What it is — a
integrations/auramodule: abeforeSettle(did)gate to run in front ofclient.pay(). Backward-looking reputation as a pre-flight axis beside PayBot's ownTRUST_VIOLATIONcheck — kept separate so the settle decision stays auditable.API
auraVerdict(did)→ typed{verdict, reason, score, ...}(trusted|caution|high_risk|new|unknown)beforeSettle(did)/requireTrust(did)→ throwsAuraUntrustedon high_risk + unknownGET /check?did=...(zero-auth). Does not sign, hold keys, or move USDC.Boundary — zero deps (global fetch, Node 18+). Off by default. Fail-closed by default; set
failOpen: trueto let an unreachable AURA pass. Purely additive — remove it and PayBot is unchanged.Tests —
npx vitest run --config integrations/aura/vitest.config.ts→ 17 offline tests via afetchImplinjection seam: every verdict class, the gate's allow-list + failOpen, the unreachablepath, input validation. Strict
tscclean.See
integrations/aura/README.md(wrapsclient.pay()) andTHREAT_MODEL.md.Opened as draft — happy to align naming/paths with paybot-sdk conventions before you merge.
Summary by CodeRabbit
Release Notes
New Features
Documentation
Tests