{
id: 'financial.transfer-per-payment-limit',
priority: 20,
appliesTo: { by: 'name', names: ['transfer_credits'] },
evaluate: (request) => {
const amount = request.args.amountCents || 0;
if (amount > request.db.config.treasuryPolicy.maxTransferPerPaymentCents) {
return {
action: 'deny',
reasonCode: 'AMOUNT_EXCEEDS_PER_PAYMENT_LIMIT',
humanMessage: `Transfer amount ${amount}c exceeds per-payment limit`,
rule: 'financial.transfer-per-payment-limit',
};
}
return null;
},
},
{
id: 'financial.transfer-hourly-limit',
priority: 30,
appliesTo: { by: 'name', names: ['transfer_credits'] },
evaluate: (request) => {
const hourlySpend = request.spendTracker.getHourlySpend('transfer');
const amount = request.args.amountCents || 0;
if (hourlySpend + amount > request.db.config.treasuryPolicy.maxTransferHourlyCents) {
return {
action: 'deny',
reasonCode: 'HOURLY_TRANSFER_LIMIT_EXCEEDED',
humanMessage: `Hourly transfer limit exceeded: ${hourlySpend}c spent + ${amount}c`,
rule: 'financial.transfer-hourly-limit',
};
}
return null;
},
},
{
id: 'financial.minimum-reserve',
priority: 25,
appliesTo: { by: 'name', names: ['transfer_credits'] },
evaluate: async (request) => {
const balance = await request.getBalance();
const amount = request.args.amountCents || 0;
const afterBalance = balance - amount;
if (afterBalance < request.db.config.treasuryPolicy.minReserveCents) {
return {
action: 'deny',
reasonCode: 'MINIMUM_RESERVE_VIOLATION',
humanMessage: `Transfer would violate minimum reserve: ${afterBalance}c < ${minReserveCents}c`,
rule: 'financial.minimum-reserve',
};
}
return null;
},
}