Skip to content

feat: invoice cloning, archival system, recipient authentication and reversible operations (#926, #927, #928, #929) - #986

Open
Barbieple-Devstem wants to merge 4 commits into
Stellar-split:mainfrom
Barbieple-Devstem:feat/issues-926-927-928-929
Open

Barbieple-Devstem wants to merge 4 commits into
Stellar-split:mainfrom
Barbieple-Devstem:feat/issues-926-927-928-929

Conversation

@Barbieple-Devstem

Copy link
Copy Markdown

Summary

Implements four features in the split contract, one commit per issue.

#926: Invoice cloning

  • clone_invoice_partial(creator, source_id, recipient_indices, overrides) copies only the selected recipients, along with their amounts and per-recipient settings (swap tokens, split rules, priorities, payout caps).
  • Before saving, every clone's recipients, amounts and deadline are checked (non-empty, matching lengths, positive amounts, no duplicate recipients, deadline in the future).
  • Approval and progress state (signatures, approved, condition_met, released_stages) is reset on the clone. Per-recipient vectors that would no longer line up with the recipients are cleared instead of being copied out of alignment.
  • Audit trail: a CloneRecord per clone (get_clone_record) and a clone history per source (get_clone_history), audit entries on both invoices, and a part_cln event.

#927: Invoice archival system

  • An admin-set ArchivalPolicy controls run_archival_sweep. The sweep is permissionless, runs at most once per interval, and resumes from a stored cursor. It archives completed invoices older than archive_after_ledgers.
  • restore_archived_invoice moves an archived invoice back to persistent storage. The restored invoice is then exempt from re-archival for a hold period.
  • Cleanup: purge_archived_invoices (or auto_purge during sweeps) drops the payment shards of invoices archived for longer than retention_ledgers.
  • Status tracking: an ArchivalRecord per invoice (get_archival_status) and ArchivalStats counters, kept up to date by lazy, explicit, batch and scheduled archival.

#928: Recipient authentication

  • RecipientAuth record with the states Unverified, ChallengeIssued, Verified, Failed, Expired and Revoked.
  • Creators opt an invoice in with set_recipient_auth_required and call issue_recipient_challenge with a bounded TTL. Each recipient then authorizes respond_recipient_challenge with sha256(challenge || recipient_xdr).
  • Late responses mark the challenge Expired, and three wrong responses mark it Failed.
  • _release refuses to pay out, and milestone payouts stay in escrow, until every recipient is verified.
  • Every state change is written to a verification audit log (get_recipient_auth_log) and emitted as an rcp_auth event.

#929: Reversible operations

  • reversible_update_deadline, reversible_update_amounts and reversible_cancel_invoice save an OperationSnapshot before changing the invoice.
  • undo_operation restores the snapshot within the rollback window (admin-set through set_rollback_window, default 1 hour). The state machine is Recorded, then either Undone or Expired.
  • Undo checks a hash of the state right after the operation, so it is rejected if the invoice has changed since. Each operation also writes audit entries and rv_rec / rv_undo events.

Closes #926
Closes #927
Closes #928
Closes #929

…ail (Stellar-split#926)

- clone_invoice_partial copies only selected recipients and their
  per-recipient settings
- validate cloned recipients, amounts and deadline before saving
- reset approval/progress state (signatures, approved, condition_met,
  released_stages) on clones
- record CloneRecord per clone and per-source clone history, append
  audit entries on source and clone, emit part_cln event
…tracking (Stellar-split#927)

- ArchivalPolicy (admin-configured) drives a rate-limited, cursor-based
  run_archival_sweep over completed invoices past archive_after_ledgers
- restore_archived_invoice moves archived data back to persistent
  storage, with a restore hold that exempts it from re-archival
- purge_archived_invoices / auto_purge drop payment shards of invoices
  archived longer than retention_ledgers
- ArchivalRecord per invoice and ArchivalStats counters track status
  across lazy, explicit, batch and scheduled archival
- audit entries and events for archive, restore, purge, sweep and
  policy updates
…yout (Stellar-split#928)

- RecipientAuth record and RecipientAuthStatus state machine
  (Unverified, ChallengeIssued, Verified, Failed, Expired, Revoked)
- creators opt invoices in with set_recipient_auth_required and issue
  per-recipient challenges with a bounded TTL
- recipients prove address control by authorizing
  respond_recipient_challenge with sha256(challenge || recipient_xdr)
- timeouts mark challenges Expired; repeated wrong responses mark Failed
- _release refuses to pay out and milestone payouts stay escrowed until
  every recipient is verified
- per-invoice verification audit log, audit entries and rcp_auth events
…ndo (Stellar-split#929)

- ReversibleOp records with a Recorded -> Undone / Expired state machine
- reversible_update_deadline, reversible_update_amounts and
  reversible_cancel_invoice capture an OperationSnapshot before mutating
- undo_operation restores the snapshot within the admin-configurable
  rollback window (set_rollback_window, default 1 hour)
- undo is validated against a hash of the post-operation state so it is
  rejected if the invoice changed since the operation
- audit entries plus rv_rec / rv_undo events for every operation
@drips-wave

drips-wave Bot commented Oct 18, 2026

Copy link
Copy Markdown

@Barbieple-Devstem Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

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.

Implement reversible operations Add recipient authentication Implement invoice archival system Add invoice cloning feature

1 participant