Skip to content

demo(payments): enforce policy before signing#97

Open
EfeDurmaz16 wants to merge 6 commits into
agentcommercekit:mainfrom
EfeDurmaz16:demo/ack-pay-policy-before-signing
Open

demo(payments): enforce policy before signing#97
EfeDurmaz16 wants to merge 6 commits into
agentcommercekit:mainfrom
EfeDurmaz16:demo/ack-pay-policy-before-signing

Conversation

@EfeDurmaz16

@EfeDurmaz16 EfeDurmaz16 commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a tiny local payment policy guard for the payments demo
  • Enforce policy after payment request verification but before returning an execution URL or signing the receipt-service payload
  • Cover approved, approval-required, and denied policy outcomes with focused tests
  • Document that this is an example pattern, not a normative ACK-Pay policy engine

Fixes #91

Review follow-ups (addressed)

  • Money handling now follows the repo-wide BigInt convention (BigInt(paymentOption.amount)), with an explicit positive-integer guard so fractional/non-positive/empty amounts the schema permits are denied instead of passing policy.
  • The autonomous spend limit is now a per-currency map keyed on currency code and expressed in each currency's subunits, so the threshold is coherent across USD (2dp) / USDC (6dp); currencies with no configured limit are denied.
  • demoPaymentPolicy is now the single source of truth — enforcePaymentPolicy spreads it and overrides only allowedRecipients, dropping the hardcoded literal.
  • README reworded to state plainly that the amount check is an illustrative per-transaction cap, not a real spend control (split-gameable without a cumulative/rate budget).
  • Optional cleanups: removed the dead parsed value and the unused assertPaymentPolicyApproved export.
  • Rebased onto latest main.

Verification

  • pnpm run build
  • pnpm --filter ./demos/payments check:types
  • pnpm --filter ./demos/payments exec vitest run
  • pnpm exec oxfmt --check demos/payments/README.md demos/payments/src/payment-policy.ts demos/payments/src/payment-policy.test.ts demos/payments/src/payment-service.ts
  • pnpm exec oxlint demos/payments/src/payment-policy.ts demos/payments/src/payment-service.ts demos/payments/src/payment-policy.test.ts
  • git diff --check

AI Usage Disclosure

This contribution was AI-assisted. Initial work used Codex CLI and the Codex app; the review follow-ups above were completed with Claude Opus. AI assistance was used for repository/docs navigation, understanding ACK/Catena context, identifying relevant issues or contribution areas, and assisting with small edits/validation. I reviewed the final diff and take responsibility for the submitted changes.

Summary by CodeRabbit

  • New Features

    • Payments now enforce a policy-based approval flow that gates autonomous transactions, applies per-currency spending caps, and requires recipient approval before returning payment URLs or signing receipts.
  • Documentation

    • Added a “policy-before-signing” example explaining approval outcomes, illustrative per-currency caps, and that the demo allowlist is derived from server identity.
  • Tests

    • Added comprehensive tests covering approval, denial, malformed amounts, per-currency limits, and allowlist behavior.

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86212e46-6c0a-491c-845b-64d6b9585e47

📥 Commits

Reviewing files that changed from the base of the PR and between 4cfc2e7 and 783fe1a.

📒 Files selected for processing (4)
  • demos/payments/README.md
  • demos/payments/src/payment-policy.test.ts
  • demos/payments/src/payment-policy.ts
  • demos/payments/src/payment-service.ts
✅ Files skipped from review due to trivial changes (1)
  • demos/payments/README.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • demos/payments/src/payment-service.ts
  • demos/payments/src/payment-policy.ts
  • demos/payments/src/payment-policy.test.ts

Walkthrough

This PR adds a local payment policy module and tests, integrates a policy enforcement gate into the payment service (applied before generating Stripe URLs and before signing receipt payloads), and documents the policy-before-signing example.

Changes

Payment policy-before-signing enforcement

Layer / File(s) Summary
Policy decision contract and configuration
demos/payments/src/payment-policy.ts
Introduces PaymentPolicyDecision discriminated union, PaymentPolicy with allowedRecipients and per-currency maxAutonomousAmount in bigint subunits, and demoPaymentPolicy default with empty allowlist and hardcoded USD/USDC limits.
Policy evaluation implementation
demos/payments/src/payment-policy.ts
Implements evaluatePaymentPolicy to parse paymentOption.amount to bigint (deny on parse failure), reject non-positive amounts, deny when currency has no configured limit (guarding prototype keys), deny when amount exceeds limit, return approval_required for unknown recipients, otherwise approved.
Policy evaluation test suite
demos/payments/src/payment-policy.test.ts
Adds Vitest coverage: approval for allowlisted below-threshold payments (including string amounts), approval_required when allowlist empty or recipient unknown, denial for over-limit and missing-currency config, per-currency subunit enforcement, non-positive and malformed amount rejection, and prototype-key currency denial.
Service integration and enforcement helpers
demos/payments/src/payment-service.ts
Adds enforcePaymentPolicy helper (throws 403 for denied, 409 for approval_required) and getTrustedRecipients (derives allowed DIDs from server private key), applies enforcement to / and /stripe-callback after option validation, and updates imports.
Policy pattern documentation
demos/payments/README.md
Documents the policy-before-signing example: where the guard runs, decision outcomes (approve/deny/approval_required), per-currency smallest-subunit caps with an explicit illustrative warning, and allowlist sourcing from configured server identity.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'demo(payments): enforce policy before signing' directly describes the main change—adding payment policy enforcement before signing in the payments demo.
Linked Issues check ✅ Passed The PR fully implements all objectives from issue #91: policy enforcement (payment amount threshold, recipient allowlist, per-currency limits), automatic signing for approved cases, approval-required outcomes for unknown recipients, denial for blocked/over-limit payments, a local policy function with no external dependency, tests covering happy and denied paths, and clarifying documentation.
Out of Scope Changes check ✅ Passed All changes directly support the policy-before-signing enforcement objective: README documentation, test coverage, policy evaluation logic, and payment service integration with policy checks.

✏️ 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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 264bbd2bf0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread demos/payments/src/payment-service.ts Outdated
const decision = evaluatePaymentPolicy(paymentOption, {
allowedRecipients: [],
maxAutonomousAmount: 1_000_000,
trustedRequestIssuer,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not trust each request's own issuer

When this payment service is reachable by any client, a third party can submit a valid PaymentRequest JWT it signed itself with a Stripe option whose recipient is that same DID; because trustedRequestIssuer is set from the token's own parsed.issuer, the empty allowlist is bypassed and the service will return a payment URL and later sign the receipt-service payload for an unapproved merchant. The policy should compare against a configured trusted server/merchant DID or explicit allowlist, not the self-asserted issuer from the request being evaluated.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in f0f5df8 by removing approval based on the Payment Request token’s own issuer. The demo now derives the autonomous recipient allowlist from the configured server identity and keeps self-asserted recipients in approval_required unless explicitly allowlisted.\n\nVerification:\n- pnpm --filter ./demos/payments test -- payment-policy.test.ts\n- pnpm exec oxfmt --check demos/payments/README.md demos/payments/src/payment-policy.ts demos/payments/src/payment-policy.test.ts demos/payments/src/payment-service.ts\n- git diff --check\n\nI also tried pnpm --filter ./demos/payments check:types, but this checkout currently fails to resolve the workspace agentcommercekit package and reports existing demo type errors outside this change.

Comment thread demos/payments/src/payment-policy.ts Outdated
paymentOption: PaymentOption,
policy: PaymentPolicy = demoPaymentPolicy,
): PaymentPolicyDecision {
const amount = Number(paymentOption.amount)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Number(paymentOption.amount) breaks the repo-wide BigInt money convention (receipt-service.ts:350, index.ts:530 both use BigInt(paymentOption.amount)) and accepts non-positive / fractional / empty string amounts the ACK-Pay schema permits (the amount string branch is unconstrained), which then pass policy and reach signing for an allowlisted recipient.

Possible Solution: use BigInt(paymentOption.amount), type maxAutonomousAmount as bigint, and add an explicit amount > 0n guard (catching the throw BigInt("1.5") raises on malformed input).

Comment thread demos/payments/src/payment-policy.ts Outdated
}
}

if (amount > policy.maxAutonomousAmount) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

amount > policy.maxAutonomousAmount compares raw subunits with no currency/decimals dimension, so one flat limit is incoherent across the USD (2dp) / USDC (6dp) / SOL options this service can receive; the documented "autonomous spend limit" does not actually bound real value.

Possible Solution: make the limit currency-aware (a per-currency map keyed on currency), or normalize to a human value per currency before comparing; reject options whose currency has no configured limit.

Comment thread demos/payments/src/payment-service.ts Outdated
) {
const decision = evaluatePaymentPolicy(paymentOption, {
allowedRecipients,
maxAutonomousAmount: 1_000_000,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

enforcePaymentPolicy hardcodes maxAutonomousAmount: 1_000_000, bypassing the exported demoPaymentPolicy.maxAutonomousAmount default entirely — so the exported config is dead/misleading and the real value has no single clear home.

Possible Solution: make demoPaymentPolicy the single source of truth — evaluatePaymentPolicy(paymentOption, { ...demoPaymentPolicy, allowedRecipients }) — and drop the literal.

Comment thread demos/payments/README.md Outdated

- known low-value recipient: continue automatically
- unknown recipient: return `approval_required`
- amount above the autonomous spend limit: deny before payment execution

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A per-transaction cap with no cumulative or rate budget is trivially defeated by splitting (e.g. 99.99 × N), yet the README presents it as "the autonomous spend limit" safety boundary.

Possible Solution: either implement a running/windowed budget, or (for a demo) reword to state plainly that this is an illustrative per-transaction check, not a real spend control, and that production needs cumulative + rate limits.

Comment thread demos/payments/src/payment-service.ts Outdated

log(colors.dim(`${name} Verifying payment request token...`))
const { paymentRequest } = await verifyPaymentRequestToken(
const { paymentRequest, parsed } = await verifyPaymentRequestToken(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small / Optional polish: parsed is destructured from verifyPaymentRequestToken and added to validatePaymentOption's return, but no caller consumes it — dead code from the earlier issuer-comparison iteration.

Possible Solution: drop parsed from the destructure and return object.

Comment thread demos/payments/src/payment-policy.ts Outdated
}
}

export function assertPaymentPolicyApproved(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small / Optional polish: assertPaymentPolicyApproved is exported but never called in the demo or tests (0 usages).

Possible Solution: remove it, or add a caller/test if it is meant to be part of the example pattern.

@venables venables left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice direction — enforcing policy at the verify→sign seam is the right shape. Requesting changes on a few items before merge (left as inline comments):

  • Money handling should follow the repo BigInt convention (Number() on amounts loses precision and accepts malformed/negative/fractional strings the schema permits).
  • The autonomous spend limit has no currency/decimals dimension, so a single flat threshold is incoherent across the USD/USDC/SOL options.
  • The effective limit is hardcoded in enforcePaymentPolicy, bypassing the exported demoPaymentPolicy default — make that the single source of truth.
  • A per-transaction cap is trivially split-gameable; either add a cumulative/rate budget or reword the README so it does not present this as a real spend control.

Plus two optional cleanups (dead parsed, unused assertPaymentPolicyApproved).

Signed-off-by: EfeDurmaz16 <efebarandurmaz05@gmail.com>
Follow the repo-wide BigInt money convention instead of Number() so the
policy no longer loses precision or accepts fractional/non-positive/empty
amounts the ACK-Pay schema's string branch permits. Replace the single flat
maxAutonomousAmount with a per-currency map keyed on currency code, expressed
in each currency's subunits, so the threshold is coherent across USD (2dp)
and USDC (6dp); currencies with no configured limit are denied. Remove the
unused assertPaymentPolicyApproved export.

Signed-off-by: EfeDurmaz16 <efebarandurmaz05@gmail.com>
enforcePaymentPolicy hardcoded maxAutonomousAmount, bypassing the exported
demoPaymentPolicy default. Spread demoPaymentPolicy and override only
allowedRecipients so the exported config is the single source of truth. Also
drop the now-dead parsed value from validatePaymentOption (no caller consumes
it after the issuer-comparison iteration was removed).

Signed-off-by: EfeDurmaz16 <efebarandurmaz05@gmail.com>
Reword the policy example so the amount check reads as an illustrative
per-transaction cap rather than a true spend control, and call out that it is
trivially split-gameable (cap x N) without a cumulative/rate-limited budget.
Document the per-currency, subunit-denominated limit and that unconfigured
currencies are denied.

Signed-off-by: EfeDurmaz16 <efebarandurmaz05@gmail.com>
@EfeDurmaz16 EfeDurmaz16 force-pushed the demo/ack-pay-policy-before-signing branch from f0f5df8 to 4cfc2e7 Compare June 4, 2026 18:54
@EfeDurmaz16

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review — all requested changes addressed, and rebased onto latest main.

Review item Resolution
BigInt money convention + reject malformed/non-positive amounts evaluatePaymentPolicy now uses BigInt(paymentOption.amount) (matching receipt-service.ts / index.ts) with an explicit amount <= 0n guard; fractional/malformed strings throw and are denied. (790ad42)
Spend limit had no currency/decimals dimension maxAutonomousAmount is now a per-currency map keyed on currency code, expressed in each currency's subunits, so the limit is coherent across USD (2dp) / USDC (6dp). Currencies with no configured limit are denied. (790ad42)
Hardcoded limit bypassed demoPaymentPolicy enforcePaymentPolicy now spreads demoPaymentPolicy and overrides only allowedRecipients; the literal is gone, so the exported config is the single source of truth. (734f40a)
Per-transaction cap presented as a real spend control README reworded to call it an illustrative per-transaction cap and to state plainly it is split-gameable (cap × N) without a cumulative/rate budget. (4cfc2e7)
Dead parsed Dropped from validatePaymentOption. (734f40a)
Unused assertPaymentPolicyApproved Removed. (790ad42)

Tests extended to cover the per-currency limit, unconfigured currencies, non-positive amounts, and malformed string amounts.

Verification:

  • pnpm run build
  • pnpm --filter ./demos/payments check:types
  • pnpm --filter ./demos/payments exec vitest run (9 passing)
  • pnpm exec oxfmt --check … and pnpm exec oxlint … (clean)
  • git diff --check

@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

🤖 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 `@demos/payments/src/payment-policy.test.ts`:
- Around line 14-133: Rename each it(...) test title to an assertive form using
the required verbs (returns/creates/requires/throws) while keeping the rest of
the description and the same test bodies; update titles referencing
evaluatePaymentPolicy/basePaymentOption accordingly (e.g., change "approves
below-threshold payments to allowed recipients" to "returns approved decision
for below-threshold payments to allowed recipients", "approves string subunit
amounts within the limit" to "returns approved decision for string subunit
amounts within the limit", "does not approve self-asserted recipients without an
allowlist" to "requires approval for self-asserted recipients without an
allowlist", "requires approval before execution for unknown recipients" to
"requires approval for unknown recipients", "denies payments above the
autonomous spend limit" to "returns denied decision for payments above the
autonomous spend limit", "applies the per-currency limit in the currency's own
subunits" to "returns approved decision when per-currency limits are respected",
"denies currencies with no configured limit" to "returns denied decision for
currencies with no configured limit", "denies non-positive amounts" to "returns
denied decision for non-positive amounts", etc.; ensure all remaining it(...)
titles follow the same assertive verb pattern.

In `@demos/payments/src/payment-policy.ts`:
- Around line 61-69: The code currently reads limit =
policy.maxAutonomousAmount[paymentOption.currency] and then compares amount >
limit, but that can pick up inherited prototype keys (e.g., "constructor") and
cause a crash; change the lookup to only accept own properties and numeric
values — e.g., use
Object.prototype.hasOwnProperty.call(policy.maxAutonomousAmount,
paymentOption.currency) (or ensure maxAutonomousAmount is Object.create(null))
before assigning/using limit, and also verify Number.isFinite(limit); if the
property is not an own property or not a finite number, treat it as undefined
and return the deterministic denial branch used for missing limits. Ensure
references: policy.maxAutonomousAmount, paymentOption.currency, amount, and
limit are updated accordingly.
🪄 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: 4ec54b36-83ae-4acf-817e-220dc938c55b

📥 Commits

Reviewing files that changed from the base of the PR and between 5ca38a4 and 4cfc2e7.

📒 Files selected for processing (4)
  • demos/payments/README.md
  • demos/payments/src/payment-policy.test.ts
  • demos/payments/src/payment-policy.ts
  • demos/payments/src/payment-service.ts

Comment on lines +14 to +133
it("approves below-threshold payments to allowed recipients", () => {
const decision = evaluatePaymentPolicy(basePaymentOption, {
allowedRecipients: [basePaymentOption.recipient],
maxAutonomousAmount: { USDC: 1_000n },
})

expect(decision).toEqual({
status: "approved",
})
})

it("approves string subunit amounts within the limit", () => {
const decision = evaluatePaymentPolicy(
{ ...basePaymentOption, amount: "50000" },
{
allowedRecipients: [basePaymentOption.recipient],
maxAutonomousAmount: { USDC: 5_000_000n },
},
)

expect(decision).toEqual({
status: "approved",
})
})

it("does not approve self-asserted recipients without an allowlist", () => {
const decision = evaluatePaymentPolicy(basePaymentOption, {
allowedRecipients: [],
maxAutonomousAmount: { USDC: 1_000n },
})

expect(decision).toEqual({
status: "approval_required",
reason: "Recipient is not on the autonomous payment allowlist",
})
})

it("requires approval before execution for unknown recipients", () => {
const decision = evaluatePaymentPolicy(basePaymentOption, {
allowedRecipients: ["did:example:trusted-merchant"],
maxAutonomousAmount: { USDC: 1_000n },
})

expect(decision).toEqual({
status: "approval_required",
reason: "Recipient is not on the autonomous payment allowlist",
})
})

it("denies payments above the autonomous spend limit", () => {
const decision = evaluatePaymentPolicy(
{
...basePaymentOption,
amount: 10_000,
},
{
allowedRecipients: [basePaymentOption.recipient],
maxAutonomousAmount: { USDC: 1_000n },
},
)

expect(decision).toEqual({
status: "denied",
reason: "Payment amount exceeds the autonomous spend limit",
})
})

it("applies the per-currency limit in the currency's own subunits", () => {
const policy = {
allowedRecipients: [basePaymentOption.recipient],
// 5.00 USD (2dp) and 5.000000 USDC (6dp) — same value, different subunits
maxAutonomousAmount: { USD: 500n, USDC: 5_000_000n },
}

// 4.00 USD is below the USD limit
expect(
evaluatePaymentPolicy(
{ ...basePaymentOption, amount: 400, decimals: 2, currency: "USD" },
policy,
),
).toEqual({ status: "approved" })

// The same 400 subunits in USDC (0.0004) is also below the USDC limit,
// confirming each currency is bounded by its own threshold
expect(
evaluatePaymentPolicy({ ...basePaymentOption, amount: 400 }, policy),
).toEqual({ status: "approved" })
})

it("denies currencies with no configured limit", () => {
const decision = evaluatePaymentPolicy(
{ ...basePaymentOption, currency: "SOL", decimals: 9 },
{
allowedRecipients: [basePaymentOption.recipient],
maxAutonomousAmount: { USDC: 1_000n },
},
)

expect(decision).toEqual({
status: "denied",
reason: "No autonomous spend limit configured for currency SOL",
})
})

it("denies non-positive amounts", () => {
const decision = evaluatePaymentPolicy(
{ ...basePaymentOption, amount: 0 },
{
allowedRecipients: [basePaymentOption.recipient],
maxAutonomousAmount: { USDC: 1_000n },
},
)

expect(decision).toEqual({
status: "denied",
reason: "Payment amount must be greater than zero",
})
})

it("denies fractional or malformed amounts the schema permits as strings", () => {

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 | ⚡ Quick win

Rename test cases to the required assertive pattern.

Current it(...) titles don’t follow the enforced creates/throws/requires/returns naming convention for *.test.ts files. Please rename these test names accordingly (for example, it("returns approved decision..."), it("requires approval..."), it("returns denied decision...")).

As per coding guidelines: Use assertive test names with patterns: "it("creates...")" , "it("throws...")" , "it("requires...")" , "it("returns...")".

🤖 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 `@demos/payments/src/payment-policy.test.ts` around lines 14 - 133, Rename each
it(...) test title to an assertive form using the required verbs
(returns/creates/requires/throws) while keeping the rest of the description and
the same test bodies; update titles referencing
evaluatePaymentPolicy/basePaymentOption accordingly (e.g., change "approves
below-threshold payments to allowed recipients" to "returns approved decision
for below-threshold payments to allowed recipients", "approves string subunit
amounts within the limit" to "returns approved decision for string subunit
amounts within the limit", "does not approve self-asserted recipients without an
allowlist" to "requires approval for self-asserted recipients without an
allowlist", "requires approval before execution for unknown recipients" to
"requires approval for unknown recipients", "denies payments above the
autonomous spend limit" to "returns denied decision for payments above the
autonomous spend limit", "applies the per-currency limit in the currency's own
subunits" to "returns approved decision when per-currency limits are respected",
"denies currencies with no configured limit" to "returns denied decision for
currencies with no configured limit", "denies non-positive amounts" to "returns
denied decision for non-positive amounts", etc.; ensure all remaining it(...)
titles follow the same assertive verb pattern.

Comment thread demos/payments/src/payment-policy.ts Outdated
An unconstrained `currency` wire string could resolve to an inherited
prototype key (e.g. "constructor"), yielding a non-bigint limit that
slipped past both the missing-limit and over-cap denials. Guard the
lookup with an own-property check and require a bigint limit so any
unconfigured currency is denied deterministically.
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.

demo(ack-pay): show policy-before-signing enforcement

2 participants