Core System Architecture Part 47 — Anonymous Payments, Resource Credits, Quotas & Privacy-Preserving Service Accounting Architecture
SIAR — Secure, Local-First, Multi-Transport Communication Platform
Series: Core System Architecture
Part: 47
Status: Architecture specification
Primary language: Rust
Builds on: Core System Architecture Parts 34–46
Primary purpose: define privacy-preserving payment, resource-credit, quota, metering, receipt, refund, and service-accounting architecture for SIAR's anonymous infrastructure without turning payment identity into a universal communication identifier.
1. Purpose
Anonymous infrastructure consumes real resources:
mixnet bandwidth
bridge bandwidth
mailbox storage
anonymous bulk storage
realtime relay capacity
CPU
egress
long-term retention
If SIAR provides paid or metered infrastructure, naive billing can destroy anonymity.
Example failure:
payment account
→ relay session
→ mailbox
→ file transfer
→ contact identity
becomes one globally correlatable graph.
The governing principle is:
Payment and resource accounting must be separated from communication identity, scoped to the minimum service context, and designed so providers can enforce quotas without learning more about the user than necessary.
2. Architectural Position
User Payment / Funding
│
▼
Privacy-Preserving Credit Issuer
│
▼
Scoped Resource Credentials
│
├── Mixnet
├── Mailbox
├── Relay
├── Bulk Storage
└── Other Services
│
▼
Usage Meter / Quota Enforcement
│
▼
Receipt / Settlement
3. Core Separation
Keep distinct:
Funding Identity
Credit Identity
Service Credential
Communication Identity
Accounting Record
Operator Settlement
4. Funding Identity
The payment processor may know:
payer
bank/card/wallet account
depending funding method.
That identity must not automatically propagate into service usage.
5. Credit Identity
Prefer unlinkable or pseudonymous credit instruments.
6. Service Credential
Each service gets a scoped credential.
7. Communication Identity
Never use:
AccountId
DeviceId
ContactId
GroupId
MailboxId
as payment-account keys.
8. Accounting Record
Contains:
resource category
usage amount
price class
receipt state
not conversation relationships.
9. Operator Settlement
Infrastructure operators may receive aggregate settlement without receiving user identity.
10. Payment Modes
#![allow(unused)] fn main() { pub enum PaymentPrivacyMode { StandardAccountBilling, PseudonymousCredits, UnlinkablePrepaidCredits, OfflineVoucher, } }
11. Standard Account Billing
Simplest.
Lowest privacy.
12. Pseudonymous Credits
Funding mapped to a non-public billing pseudonym.
Better separation.
13. Unlinkable Prepaid Credits
Preferred high-privacy mode.
Concept:
pay once
→ receive blinded/unlinkable spendable resource credits
→ spend credits at services
14. Offline Voucher
Useful for:
gift codes
cash-like distribution
offline bootstrap
15. Do Not Invent Payment Cryptography
Use reviewed:
blind signatures
anonymous credentials
privacy-preserving e-cash
if implemented.
16. Initial Production Recommendation
Start with:
prepaid pseudonymous resource credits
then add stronger unlinkable credits after dedicated cryptographic review.
17. Resource Credit
#![allow(unused)] fn main() { pub struct ResourceCredit { pub credit_id: ResourceCreditId, pub class: ResourceClass, pub units: u64, pub expires_at: Option<Timestamp>, pub proof: CreditProof, } }
18. Credit ID
Provider-facing ID should be random or unlinkable.
19. Resource Classes
#![allow(unused)] fn main() { pub enum ResourceClass { MixnetBandwidth, MailboxStorage, RelayMinutes, BulkStorage, BulkEgress, RealtimeRelay, BridgeBandwidth, } }
20. Avoid Universal Currency Internally
Using one universal token everywhere can increase cross-service linkability.
21. Scoped Credit Classes
Preferred:
mailbox credit
relay credit
bulk storage credit
22. Cross-Service Conversion
Can happen at issuer boundary.
23. Service-Specific Spend Token
#![allow(unused)] fn main() { pub struct ServiceSpendToken { pub service: ServiceClass, pub amount: u64, pub nonce: [u8; 16], pub proof: SpendProof, } }
24. Spend Token Scope
Bound to:
service class
amount
expiry
25. One-Time Spend
Preferred.
26. Double-Spend Problem
If token is one-time, provider must reject reused token.
27. Double-Spend Store
#![allow(unused)] fn main() { pub trait SpentTokenStore { fn check_and_mark( &self, token: SpendTokenId, ) -> Result<SpendStatus, AccountingError>; } }
28. Privacy Constraint
Spent-token storage should not contain communication identifiers.
29. Spend Status
#![allow(unused)] fn main() { pub enum SpendStatus { Fresh, AlreadySpent, Invalid, } }
30. Partial Spend
Two options:
fixed denomination tokens
or
change tokens
31. Fixed Denominations
Simpler.
32. Change Token
More efficient, more complex.
33. Initial Recommendation
Use fixed/coarse denomination resource vouchers.
34. Denomination Privacy
Coarse units reduce exact usage fingerprinting.
35. Example Denominations
Illustrative:
10 MB
100 MB
1 GB
1 relay hour
1 mailbox-month
Exact pricing is product policy, not architecture.
36. Quota Model
Not all resource control requires payment.
Some can be:
free tier
earned credits
operator grant
paid credit
37. Quota Credential
#![allow(unused)] fn main() { pub struct QuotaCredential { pub scope: QuotaScope, pub limit: ResourceLimit, pub period: QuotaPeriod, pub proof: QuotaProof, } }
38. Quota Scope
#![allow(unused)] fn main() { pub enum QuotaScope { Service(ServiceClass), Capability(CapabilityScopeId), Community(CommunityId), } }
39. No Global User Quota ID Required
Hard rule.
40. Resource Limit
#![allow(unused)] fn main() { pub enum ResourceLimit { Bytes(u64), Objects(u64), Duration(Duration), Operations(u64), } }
41. Quota Period
#![allow(unused)] fn main() { pub enum QuotaPeriod { PerSession, Daily, Monthly, Lifetime, } }
42. Privacy-Preserving Metering
Provider needs to know:
how much resource consumed
but not:
who user's contacts are
43. Metering Principle
Meter at the service boundary.
44. Example
Mailbox provider may know:
opaque mailbox capability consumed 50 MB
not:
Alice received messages from Bob
45. Meter Event
#![allow(unused)] fn main() { pub struct MeterEvent { pub service: ServiceClass, pub resource: ResourceMeasurement, pub accounting_scope: AccountingScopeId, pub timestamp_bucket: TimeBucket, } }
46. Accounting Scope ID
Random/scoped.
Not reusable across unrelated services.
47. Timestamp Bucketing
Avoid unnecessarily precise billing timestamps.
48. Exact Timestamp
May be required internally for fraud/consistency.
Retention should be minimized.
49. Aggregation
Prefer:
usage totals
over per-packet billing records.
50. No Per-Message Charge Record
Hard rule where possible.
51. Batch Accounting
Aggregate:
N MB
per accounting interval
52. Usage Bucket
#![allow(unused)] fn main() { pub struct UsageBucket { pub scope: AccountingScopeId, pub period: AccountingPeriod, pub usage: ResourceMeasurement, } }
53. Accounting Period
Could be:
hour
day
billing cycle
54. Service Receipt
#![allow(unused)] fn main() { pub struct ServiceReceipt { pub receipt_id: ReceiptId, pub service: ServiceClass, pub consumed: ResourceMeasurement, pub credit_spent: u64, pub period: AccountingPeriod, pub proof: ReceiptProof, } }
55. Receipt Privacy
Receipt should not contain:
contact
conversation
peer IP
group
56. Receipt Purpose
Useful for:
local accounting
refund
dispute
operator settlement
57. Receipt Authenticity
Provider signs receipt.
58. User Wallet
Local-first wallet stores:
credits
spent state
receipts
refund state
59. Wallet Identity
Separate from messaging identity.
60. Wallet Storage
Encrypted.
61. Wallet Backup
Needs separate recovery policy.
62. Credit Backup
Some anonymous credit systems may not safely support naïve duplication.
63. Double-Spend Risk on Restore
Restoring same spendable token to two devices can create double-spend.
64. Therefore
Credit recovery architecture must define:
single active wallet
or
issuer-side recovery/reissue
65. Wallet Recovery Policy
#![allow(unused)] fn main() { pub enum WalletRecoveryPolicy { SingleDeviceAuthority, IssuerReissue, NonRecoverableBearerCredits, } }
66. Bearer Credits
Like cash:
loss may be irreversible
67. UX Honesty
If bearer token cannot be recovered, say so clearly.
68. Multi-Device Wallet
Avoid simply copying bearer tokens to every device.
69. Better
Allocate separate credit subsets per device.
70. Device Credit Pool
#![allow(unused)] fn main() { pub struct DeviceCreditPool { pub device_wallet_id: DeviceWalletId, pub credits: Vec<ResourceCreditRef>, } }
71. Transfer Between Devices
Use wallet transfer protocol.
72. Offline Spend
Possible for certain vouchers.
73. Offline Double-Spend
Hard problem.
74. Initial Recommendation
Require online validation for reusable/high-value credit spend.
75. Low-Value Offline Voucher
Could be accepted with bounded risk.
76. Free Credits
Issuer may grant:
signup
community subsidy
operator promotion
77. Subsidy Privacy
Should not turn into identity marker.
78. Anonymous Voucher Distribution
Useful for:
aid
community access
emergency communication
79. Voucher Code
High entropy.
80. Voucher Redemption
Issuer returns resource credits.
81. Voucher Abuse
Rate-limit redemption.
82. Pricing Model
Architecture supports:
fixed price
dynamic price
operator-defined price
subscription package
83. Dynamic Pricing Privacy
Frequent price queries can reveal activity.
84. Signed Price Catalog
Clients can fetch generic price table.
85. Price Catalog
#![allow(unused)] fn main() { pub struct PriceCatalog { pub version: u64, pub prices: Vec<ServicePrice>, pub valid_until: Timestamp, pub signature: PriceSignature, } }
86. No Per-User Pricing in Strict Mode
Hard rule.
87. Operator-Specific Pricing
Possible if topology/provider selection supports it.
88. Service Price
#![allow(unused)] fn main() { pub struct ServicePrice { pub service: ServiceClass, pub unit: ResourceUnit, pub cost: u64, } }
89. Price Unit
#![allow(unused)] fn main() { pub enum ResourceUnit { Megabyte, Gigabyte, Minute, Object, Month, Operation, } }
90. Subscription
Could grant periodic scoped credits.
91. Subscription Credential
Do not expose billing account directly to provider.
92. Subscription Issuer
Issuer converts subscription entitlement to:
service credits
93. Wallet Balance
Local.
94. Provider Should Not Query User's Full Balance
Hard rule.
95. Spend Authorization
Present only enough credit for requested service.
96. Credit Reservation
Needed for long operations.
Example:
2-hour call
97. Reservation
#![allow(unused)] fn main() { pub struct CreditReservation { pub reservation_id: ReservationId, pub service: ServiceClass, pub max_amount: u64, pub expires_at: Timestamp, } }
98. Reservation Flow
reserve
→ consume
→ finalize
→ refund unused
99. Realtime Relay Accounting
Meter:
relay minutes
bandwidth
100. Call Privacy
Relay accounting scope must not expose peer identities.
101. Mixnet Accounting
Meter:
bandwidth/cells
102. Critical Warning
Per-packet payment tokens can make packets linkable.
103. Better
Use:
short-lived quota credential
for many packets.
104. Mixnet Session Credit
#![allow(unused)] fn main() { pub struct MixnetQuotaCredential { pub quota_id: [u8; 32], pub cell_budget: u64, pub expires_at: Timestamp, pub proof: QuotaProof, } }
105. Quota ID Rotation
Frequent.
106. Provider Visibility
Entry gateway may see quota credential.
Downstream mix nodes should not need it.
107. No Payment Marker Inside Sphinx Route
Hard rule.
108. Mailbox Accounting
Meter:
storage bytes
retention
fetch egress
109. Mailbox Identity Separation
Billing scope separate from mailbox ID if practical.
110. Bulk Storage Accounting
Meter:
stored bytes × retention
egress
operations
111. Bulk Provider
Uses anonymous object billing scope.
112. Object Billing Linkability
Do not reuse one stable billing ID for all objects.
113. Object-Level Credit
Possible for high privacy.
114. Bridge Accounting
May meter:
bandwidth
session duration
115. Bridge Free Tier
Likely useful to avoid access failure under censorship.
116. Emergency Access
Architecture may allow:
emergency zero-cost quota
with abuse controls.
117. Emergency Abuse
Must be bounded.
118. Resource Credit Transfer
Users may transfer credits.
119. Privacy Risk
Transfers can create social graph.
120. Initial Recommendation
Do not support user-to-user credit transfer in first release.
121. Gift Voucher
Issuer-mediated gift code safer.
122. Refund
Possible when service fails before consumption.
123. Refund Token
#![allow(unused)] fn main() { pub struct RefundClaim { pub receipt_id: ReceiptId, pub unused: u64, pub provider_proof: ReceiptProof, } }
124. Refund Privacy
Issuer should not need communication details.
125. Refund Abuse
Prevent double refund.
126. Refund State
#![allow(unused)] fn main() { pub enum RefundState { Eligible, Claimed, Rejected, Expired, } }
127. Service Failure
Unused reservation returned.
128. Provider Crash
Receipt/reconciliation mechanism required.
129. Idempotent Settlement
Hard rule.
130. Accounting Ledger
Use append-only accounting ledger.
131. Ledger Scope
Financial/resource events only.
No communication metadata.
132. Ledger Entry
#![allow(unused)] fn main() { pub struct AccountingEntry { pub entry_id: AccountingEntryId, pub service: ServiceClass, pub accounting_scope: AccountingScopeId, pub delta: ResourceDelta, pub reason: AccountingReason, pub timestamp_bucket: TimeBucket, } }
133. Accounting Reason
#![allow(unused)] fn main() { pub enum AccountingReason { CreditIssued, CreditReserved, CreditConsumed, CreditRefunded, CreditExpired, } }
134. Double-Entry Accounting
Useful internally.
135. Privacy Boundary
Double-entry does not imply identity linkage.
136. Issuer Ledger
Tracks:
credits issued
credits redeemed
137. Provider Ledger
Tracks:
resource consumed
receipts
settlement
138. Settlement Aggregator
Pays operator aggregate amounts.
139. Operator Settlement Record
#![allow(unused)] fn main() { pub struct OperatorSettlement { pub operator: OperatorId, pub period: AccountingPeriod, pub service: ServiceClass, pub units: u64, pub amount: SettlementAmount, } }
140. No User Mapping
Hard rule.
141. Fraud Detection
Possible threats:
double spend
forged credit
replayed token
meter under-reporting
provider over-reporting
refund fraud
142. Credit Authenticity
Issuer signs/proves credit.
143. Provider Receipt
Provider signs consumption.
144. Cross-Checking
Issuer can reconcile:
spent credits
provider receipts
without communication identity.
145. Provider Over-Billing
User can verify signed usage receipt against local meter where possible.
146. Local Meter
Client keeps expected usage.
147. Tolerance
Network overhead may differ.
148. Dispute
User submits:
receipt
local measurement
not conversation content.
149. Abuse Rate Limiting
Free anonymous services need quota.
150. Free Quota Token
#![allow(unused)] fn main() { pub struct FreeTierCredential { pub service: ServiceClass, pub allowance: u64, pub period: QuotaPeriod, pub proof: QuotaProof, } }
151. Sybil Problem
Anonymous users can repeatedly claim free quota.
152. Possible Defenses
device-bound coarse grant
proof-of-work
invite credential
operator-issued voucher
payment-backed grant
153. Privacy vs Sybil Resistance
No perfect solution.
154. Device Binding
Can hurt privacy.
Use only if policy explicitly accepts it.
155. Proof-of-Work
Consumes battery.
Use carefully.
156. Human Verification
Could be optional.
157. Invite-Based Free Quota
Useful for communities.
158. Free Tier Policy
Separate from paid anonymous credits.
159. Resource Quota Service
#![allow(unused)] fn main() { pub trait ResourceQuotaService { fn authorize( &self, credential: &QuotaCredential, request: ResourceRequest, ) -> Result<QuotaAuthorization, QuotaError>; fn consume( &self, authorization: QuotaAuthorization, actual: ResourceMeasurement, ) -> Result<ServiceReceipt, QuotaError>; } }
160. Credit Wallet Trait
#![allow(unused)] fn main() { pub trait AnonymousCreditWallet { fn balance( &self, class: ResourceClass, ) -> Result<ResourceBalance, WalletError>; fn prepare_spend( &self, request: SpendRequest, ) -> Result<ServiceSpendToken, WalletError>; fn apply_receipt( &self, receipt: ServiceReceipt, ) -> Result<(), WalletError>; } }
161. Credit Issuer Trait
#![allow(unused)] fn main() { #[async_trait] pub trait CreditIssuer: Send + Sync { async fn issue( &self, funding: FundingReceipt, request: CreditIssueRequest, ) -> Result<Vec<ResourceCredit>, CreditError>; async fn redeem_refund( &self, claim: RefundClaim, ) -> Result<ResourceCredit, CreditError>; } }
162. Funding Adapter
Payment processors remain outside anonymous service plane.
163. Funding Methods
Architecture can support:
card
bank transfer
wallet
gift voucher
organization grant
164. Privacy Caveat
Traditional payment processor may know payer identity.
165. Separation Goal
Processor should not learn:
which contacts
which mailbox
which group
which relay call
166. Funding Receipt
#![allow(unused)] fn main() { pub struct FundingReceipt { pub issuer_reference: OpaqueFundingReference, pub amount: FundingAmount, pub status: FundingStatus, } }
167. Opaque Funding Reference
Never propagated to service provider.
168. KYC Boundary
If legally required for a payment provider, keep KYC at funding boundary.
169. No KYC Propagation
Hard rule unless law/product specifically requires a service identity.
170. Regional Compliance
Payment laws differ.
Architecture must support:
provider-specific funding adapters
without altering anonymous-service credentials.
171. Tax/Invoice Boundary
Invoice may identify payer.
Keep separate from anonymous usage receipts.
172. Business Receipt
Separate artifact.
173. Service Usage Receipt
Pseudonymous/scoped.
174. Account Billing Mode
If user chooses convenience:
subscription account
can still convert entitlement into service-scoped credits.
175. Wallet Top-Up
Flow:
fund
→ issuer confirms
→ wallet receives credits
176. Auto Top-Up
Privacy concern.
Repeated automated funding correlates usage.
177. Strict Privacy Recommendation
Prefer manual/prepaid larger top-ups.
178. Auto Top-Up Option
Explicit convenience mode.
179. Low Balance Notification
Local.
180. Provider Should Not Send Identity-Linked Billing Notification
Hard rule.
181. Expiry
Credits may expire for business reasons.
182. Expiry Privacy
Do not force spend pattern before exact short deadline unnecessarily.
183. Credit Consolidation
Combining credits can increase linkability.
184. Avoid Provider-Side Consolidation
Wallet can select tokens locally.
185. Coin Selection Analogy
Choose credits to minimize:
linkability
waste
186. Wallet Selection Policy
#![allow(unused)] fn main() { pub enum CreditSelectionPolicy { MinimizeChange, MinimizeLinkability, OldestFirst, } }
187. Strict Mode
Prefer:
MinimizeLinkability
188. Receipt Linkability
One stable wallet receipt ID across services is bad.
189. Per-Service Receipt Namespace
Required.
190. Accounting Correlation Attack
Adversary combines:
funding timestamp
credit issuance
service spend
traffic timing
191. Mitigations
prepay
batch issuance
coarse denominations
delayed use
service-specific tokens
192. Timing Separation
Do not require immediate:
fund → spend
193. Issuance Batching
Useful for unlinkability.
194. Blind Issuance
Future strong solution.
195. Privacy Lab Integration
Part 42 should test:
funding-to-usage correlation
cross-service credit correlation
quota ID lifetime
receipt linkage
196. Maximum Privacy
Recommended:
prepaid
service-scoped
short-lived quota credentials
local wallet
no identity-linked provider account
197. Service Denial
If no credit:
service unavailable
not privacy downgrade.
198. Example
No private relay credits:
private call cannot start
not:
use direct call silently
199. Emergency Free Path
If product provides, must be explicit and bounded.
200. Wallet UX
Show:
Mixnet bandwidth
Mailbox storage
Relay time
Bulk storage
rather than one opaque score if credits are scoped.
201. Simplified UX
Can show converted estimated balance locally.
202. No Provider-Side Unified User Wallet Required
Hard rule.
203. Spend Confirmation
For large spend:
confirm
204. Small Spend
Automatic under local budget.
205. Budget Policy
#![allow(unused)] fn main() { pub struct WalletBudgetPolicy { pub auto_spend_limit: u64, pub daily_limit: Option<u64>, } }
206. Child/Managed Profiles
Separate product policy.
207. Organization Grants
Organization can issue service credits.
208. Grant Privacy
Organization may know grant recipient.
Provider still should not learn user's communications.
209. Community Credits
Can subsidize group/community service.
210. Group Quota
Group capability may carry pooled credit.
211. Privacy Risk
Pooled credit links group usage.
212. Strict Group Mode
Prefer member-specific anonymous service credits.
213. Infrastructure Operator Payments
Operators need compensation.
214. Settlement Input
Aggregate:
valid receipts
resource units
service class
215. Operator Privacy
Operator identity can be public/governance identity.
216. User Privacy
Operator does not need user identity.
217. Settlement Fraud
Operator may fabricate usage.
218. Countermeasures
signed spend tokens
client receipts
issuer reconciliation
capacity audits
219. No Packet-Level Settlement Logging
Hard rule.
220. Accounting Retention
Different layers:
wallet receipts
issuer spend proofs
provider aggregate ledger
settlement records
221. Retention Minimum
Only as long as:
fraud
refund
accounting
legal
requires.
222. Deletion
Service-specific identifiers should expire.
223. Audit
Accounting audit must not expose communication graph.
224. Finance Audit Export
Contains:
amounts
service categories
settlements
not message metadata.
225. Observability
Safe metrics:
credits issued
credits redeemed
quota failures
refund count
settlement totals
226. Forbidden Metrics
No:
AccountId + mailbox ID
AccountId + relay session
contact + spend
group + payer identity
227. Remote Telemetry
Do not log token serials into general telemetry.
228. Support Bundle
Redact:
unspent tokens
spend proofs
funding references
229. Security Threats
token theft
double spend
forgery
replay
rollback
wallet cloning
receipt forgery
provider overbilling
issuer compromise
230. Token Theft
Bearer credit stolen = spend risk.
231. Wallet Protection
Use:
OS secure store
encrypted DB
device authentication
232. Wallet Cloning
Detect/restrict via issuer rules if recoverable model.
233. Backup Rollback
Restoring old wallet state can replay spent credits.
234. Anti-Rollback
Spent-state reconciliation required.
235. Non-Recoverable Cash Mode
Alternative avoids issuer account but increases loss risk.
236. Issuer Compromise
Can mint fraudulent credits.
237. Issuer Key Rotation
Required.
238. Offline Root
Recommended for credit-signing hierarchy.
239. Provider Verification Keys
Distributed via signed catalog.
240. Credit Versioning
#![allow(unused)] fn main() { pub struct CreditVersion(pub u16); }
241. Unknown Version
Reject safely.
242. Price Catalog Anti-Rollback
Required.
243. Wallet Schema
Potential:
resource_credits
spent_tokens
service_receipts
credit_reservations
refund_claims
wallet_policy
244. Provider Accounting Schema
Potential:
quota_credentials
spent_token_ids
usage_buckets
service_receipts
settlement_batches
245. Issuer Schema
Potential:
funding_receipts
credit_issuance
redeemed_spends
refunds
issuer_key_epochs
246. Secret Storage
Unspent credit secrets stored securely.
247. Transactionality
Spend flow:
reserve token
→ send
→ provider confirms
→ mark spent
→ persist receipt
must be crash-safe.
248. Crash Ambiguity
If crash after provider accepts but before wallet records receipt:
token considered potentially spent
249. Spend Reconciliation
Query using privacy-safe receipt/spend proof.
250. Never Retry Same One-Time Token Blindly
Hard rule.
251. State Machine
#![allow(unused)] fn main() { pub enum SpendState { Available, Reserved, Submitted, Confirmed, Uncertain, Refunded, } }
252. Uncertain State
Conservative.
253. Reconciliation
Resolve:
Confirmed
or
Refundable/Available
only with provider/issuer proof.
254. Formal Verification Targets
Strong candidates:
spend state machine
double-spend prevention
reservation/refund
wallet restore
settlement idempotency
255. TLA+ Candidate
Credit reservation / consume / refund workflow.
256. Kani Candidate
Token scope and denomination validation.
257. Loom Candidate
Concurrent spend attempts.
258. Fuzzing
Fuzz:
credit token
quota credential
receipt
price catalog
refund claim
259. Property Tests
Properties:
one-time token cannot be successfully spent twice
provider cannot consume more than authorized quota
refund plus spend cannot exceed original credit
strict service never uses identity-linked fallback
260. Double-Spend Race Test
Two providers simultaneously receive same token.
261. Crash Tests
Crash at every spend transition.
262. Wallet Restore Tests
Old backup cannot create valid duplicate spending.
263. Price Tests
Old catalog rejected after newer accepted.
264. Receipt Forgery Test
Invalid provider signature rejected.
265. Provider Overbilling Test
Receipt over reservation rejected.
266. Quota Exhaustion Test
Service stops safely.
267. Privacy Tests
Verify service provider cannot infer:
funding account
contact identity
group identity
from credential schema.
268. Cross-Service Correlation Test
Tokens for:
mailbox
relay
bulk storage
must not share stable IDs.
269. Performance Tests
Measure:
token verification
quota authorization
wallet selection
settlement aggregation
270. Scale Tests
High-rate:
millions of spend tokens
large spent-token store
settlement batches
271. Privacy-Safe Spent Set
If using probabilistic structure, false-positive impact must be analyzed.
272. Exact Store Initially
Recommended.
273. Pruning
Spent token records can expire after token lifetime + dispute window.
274. Crate Layout
Recommended:
crates/
├── siar-accounting-core/
├── siar-credit-wallet/
├── siar-credit-issuer/
├── siar-credit-token/
├── siar-quota/
├── siar-metering/
├── siar-receipts/
├── siar-refunds/
├── siar-price-catalog/
├── siar-settlement/
├── siar-accounting-observability/
└── siar-accounting-testkit/
275. siar-accounting-core
Owns:
service classes
resource units
accounting IDs
errors
276. siar-credit-wallet
Local encrypted wallet.
277. siar-credit-issuer
Funding-to-credit issuance.
278. siar-credit-token
Spend token formats/proofs.
279. siar-quota
Quota credentials/authorization.
280. siar-metering
Usage aggregation.
281. siar-receipts
Signed service receipts.
282. siar-refunds
Refund claims/state.
283. siar-price-catalog
Signed pricing.
284. siar-settlement
Operator aggregation/payout.
285. siar-accounting-observability
Privacy-safe metrics.
286. siar-accounting-testkit
Fake issuer/provider/fraud tests.
287. Error Taxonomy
#![allow(unused)] fn main() { pub enum AccountingError { CreditInvalid, CreditExpired, CreditInsufficient, DoubleSpend, QuotaExceeded, ReservationExpired, ReceiptInvalid, RefundAlreadyClaimed, PriceCatalogStale, SettlementConflict, WalletLocked, Internal, } }
288. Security Invariants
Mandatory:
1. Funding identity never becomes a universal communication identifier.
2. Service credentials are scoped and do not reuse AccountId/DeviceId/ContactId.
3. Mixnet packet routing never embeds payment identity.
4. Cross-service credits do not expose one stable provider-visible wallet ID.
5. One-time spend tokens cannot be accepted twice.
6. Receipt and refund processing is idempotent.
7. Strict privacy services never downgrade when credits are unavailable.
8. Provider receipts contain no contact/conversation/group identity.
9. Wallet backups cannot safely duplicate spendable bearer credit state.
10. Operator settlement is aggregate and does not require user identity.
11. Unspent bearer secrets never appear in telemetry/support bundles.
12. Payment cryptography uses reviewed constructions rather than custom schemes.
289. Initial Production Scope
Implement first:
local encrypted resource wallet
service-scoped prepaid credits
fixed denominations
short-lived quota credentials
signed price catalog
service receipts
reservation/finalize/refund
exact double-spend store
aggregate operator settlement
strict separation from communication IDs
privacy-safe diagnostics
Then add:
blind/unlinkable credit issuance
anonymous e-cash style spending
offline vouchers
privacy-preserving free-tier credentials
threshold issuer signing
advanced fraud proofs
290. Definition of Done
Part 47 is complete when:
- funding identity and communication identity are cleanly separated
- resource/service credit types are scoped
- no universal provider-visible wallet identity is required
- quotas can be enforced without social graph access
- mixnet/mailbox/relay/bulk services have explicit accounting boundaries
- one-time token and double-spend handling are defined
- reservations, refunds, receipts, and crash ambiguity are handled
- wallet backup/recovery does not clone bearer credits unsafely
- operator settlement is aggregate and privacy-preserving
- signed pricing and anti-rollback are defined
- free-tier/Sybil tradeoffs are explicit
- telemetry/support bundles exclude payment secrets and cross-service linkable IDs
- property/formal/fraud/privacy tests are specified
- stronger blind/unlinkable credits remain a reviewed future layer rather than ad hoc cryptography
291. Final Architecture
FUNDING SOURCE
│
▼
CREDIT ISSUER
│
Scoped Credits
│
┌──────────────┼──────────────┐
│ │ │
Mixnet Mailbox Relay/Bulk
│ │ │
▼ ▼ ▼
Quota/Meter Quota/Meter Quota/Meter
│ │ │
└──────────────┼──────────────┘
▼
Signed Receipts
│
▼
Aggregate Settlement
Strict privacy model:
funding identity
↓
issuer boundary
↓
scoped/unlinkable credit
↓
service quota credential
↓
anonymous service usage
not:
billing account
→ permanent ID
→ every relay/mailbox/file/call
292. Final Principle
Private communication infrastructure can be paid for without turning billing into a social-graph database.
The correct model is:
prepaid/scoped credits
+
service-local quota credentials
+
minimal metering
+
signed receipts
+
aggregate settlement
+
strict identity separation
not:
one account ID attached to every resource event
This architecture gives SIAR a path to sustainable paid infrastructure while preserving the anonymity and metadata-separation guarantees established in Parts 34–46.