Skip to content

feat: closed-loop Square payment validation#10

Open
gudnuf wants to merge 4 commits intostrike-backendfrom
square-closed-loop
Open

feat: closed-loop Square payment validation#10
gudnuf wants to merge 4 commits intostrike-backendfrom
square-closed-loop

Conversation

@gudnuf
Copy link

@gudnuf gudnuf commented Feb 11, 2026

Summary

  • Adds cdk-agicash crate that wraps the Strike backend to restrict melts to invoices from a configured Square merchant
  • Validates invoices by matching description + creation timestamp against synced Square payments (polling, webhook, and on-demand sync)
  • Adds PaymentNotAllowed error code (20739) to cdk-common so rejected invoices return a user-facing message: "This ecash can only be spent at {store_name}"
  • Integrates into cdk-mintd behind the agicash feature flag
  • Updates Dockerfiles to build with --features agicash

Test plan

  • Verify clippy passes on cdk-agicash and cdk-common (cargo clippy -p cdk-agicash -p cdk-common --all-features --lib --bins -- -D warnings)
  • Verify workspace tests pass (cargo test --lib --workspace --exclude cdk-postgres)
  • Test with a running Square-integrated Strike setup: melt against a valid Square invoice succeeds, melt against a non-Square invoice returns {"code": 20739, "detail": "This ecash can only be spent at ..."}

🤖 Generated with Claude Code

The Prefer header is used by NUT-20 for long-polling support but was
being blocked by the CORS middleware. Add it to the allowed headers
list for both auth and non-auth configurations.
Drop internal payment/settlement tracking and correlation ID embedding
which were unused complexity. Add webhook subscription rotation to
prevent hitting Strike's 50-subscription limit, and validate webhook
URLs require HTTPS.
Add cdk-agicash crate that wraps Strike backend to restrict melts to
invoices from a configured Square merchant. Validates by matching invoice
description and timestamp against synced Square payments (polling +
webhook + on-demand sync). Rejected invoices return PaymentNotAllowed
(20739) with user-facing message.
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