Skip to content

fix(soroban): implement storage TTL retention policy and archival reliability - #537

Open
akinboyewaSamson wants to merge 2 commits into
ZyntariHQ:mainfrom
akinboyewaSamson:fix/storage-ttl-archival-policy
Open

fix(soroban): implement storage TTL retention policy and archival reliability#537
akinboyewaSamson wants to merge 2 commits into
ZyntariHQ:mainfrom
akinboyewaSamson:fix/storage-ttl-archival-policy

Conversation

@akinboyewaSamson

@akinboyewaSamson akinboyewaSamson commented Aug 30, 2026

Copy link
Copy Markdown

closes #465

Summary

Fixes a critical reliability gap in the on-chain invoice payment log. The contract claimed records "survive ledger archival" but BUMP_TTL was only 518,400 ledgers (~30 days) and entries were only extended on access — meaning untouched audit records would be silently archived after ~30 days.

Changes

Storage & TTL Policy

  • Raise MIN_TTL to 120,960 ledgers (~7 days) and BUMP_TTL to 1,555,200 ledgers (~90 days)
  • Introduce tiered retention: permanent instance storage + quarterly persistent rent window

Archival Differentiation

  • Add ContractError::PaymentArchived (code 24) — distinguishes archived records from records that were never created
  • get_payment returns PaymentArchived when the persistent slot expired but the write log (PaymentLog) confirms the invoice was settled
  • PaymentHistoryPage gains archived_skipped field alongside gaps_skipped

Bulk TTL Extension

  • New admin-gated extend_history_ttl entrypoint — extends up to MAX_TTL_EXTEND_BATCH (20) records per call, exempt from contract pause
  • CLI ops scripts: invoke-extend-history-ttl.sh and invoke-restore-record.sh

Index & Counter Drift Fix

  • rebuild_payment_history_index and is_index_complete now correctly handle archived slots, preventing PaymentHistoryCount drift and false alarms in history_index_status

Backend Protection

  • hasInvoicePayment in soroban.service.ts treats PaymentArchived as confirmed on-chain, preventing double-anchoring of settled invoices

TypeScript Client

  • error-manifest.ts: code 24 PaymentArchived
  • types.ts: PaymentHistoryPage.archivedSkipped, ExtendHistoryTtlResult
  • codec.ts: updated decodePaymentHistoryPage, exported MAX_TTL_EXTEND_BATCH
  • soroban-invoice-client.ts: new extendHistoryTtl method

Documentation

  • soroban/docs/retention-and-restore.md: retention policy and restore runbook
  • soroban/README.md: updated error codes, retention policy, CLI scripts

Tests

  • test_archived_payment_distinguished_from_not_found
  • test_payment_history_distinguishes_archived_from_corrupted_slots
  • test_extend_history_ttl_admin_auth_and_batching
  • test_extend_history_ttl_succeeds_while_paused
  • test_history_index_status_remains_consistent_on_archival
  • test_rebuild_history_index_with_archived_records_preserves_count_and_mapping

… and archival reliability

- Add tiered retention model: permanent instance storage and quarterly persistent rent window
- Update MIN_TTL to 120,960 ledgers (~7 days) and BUMP_TTL to 1,555,200 ledgers (~90 days)
- Introduce ContractError::PaymentArchived (code 24) to distinguish archival from PaymentNotFound
- Add extend_history_ttl admin-gated entrypoint and MAX_TTL_EXTEND_BATCH (20)
- Differentiate archived_skipped from gaps_skipped in PaymentHistoryPage
- Fix rebuild_payment_history_index and is_index_complete to prevent counter drift upon entry archival
- Prevent backend re-anchoring of archived invoices in hasInvoicePayment
- Add invoke-extend-history-ttl.sh and invoke-restore-record.sh CLI ops scripts
- Document retention policy and restore procedures in retention-and-restore.md and README.md
- Add comprehensive contract and client tests
- rebuild_payment_history_index: guard against clobbering V0-era PaymentHistory
  entries when PaymentLog is empty (payment_count==0 but existing_count>0)
- migrate_schema_v1_to_v2: same guard prevents write_history_index wiping
  pre-log V0 records during full upgrade chain
- rebuild now bypasses get_payment() PaymentArchived sentinel by reading
  PaymentV1/legacy keys directly via new read_payment_value_v1/legacy helpers
- test: deadlock loop test tracks archived_skipped instead of gaps_skipped
- test: rebuild test correctly calls rebuild before asserting restored state
- storage: expose read_payment_value_v1 and read_payment_value_legacy for
  migration use
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.

Define a retention policy and TTL strategy so payment records are not archived out of the audit log

2 participants