HANDOFF: target project invoice

Scope
Only invoice requirements are authoritative. Ignore all archived records for other projects. Updates 1–5 have been applied; superseded values are discarded. Future updates and questions are not yet available.

CURRENT choices
{
  "currency": "USD",
  "rounding": "invoice",
  "duplicate_event": "last",
  "inclusive_limit": false,
  "max_refund_age_days": 45,
  "refunds_first": false,
  "refund_overflow": "reject",
  "void_is_tombstone": false,
  "fee_refundable": true,
  "min_invoice_cents": 25,
  "status_case": "upper",
  "order": "created"
}

Fixed interface
Implement evaluate(payload) -> {invoices:[{id,charge,refunded,balance,status}]}.
Do not mutate payload. Empty input returns {"invoices":[]}.

Input contract
Invoices have unique id, integer created day, currency, lines containing nonnegative decimal-dollar strings, nonnegative fee_cents, and ordered events.
Each event has eid, kind (refund/void/restore), day, and nonnegative cents.

Current processing requirements
1. Filter out invoices whose currency is not USD.
2. Sum line amounts exactly as decimals, then convert the sum to integer cents using ROUND_HALF_UP. Do not round each line separately.
3. Principal is that rounded line sum. charge = principal + fee_cents.
4. Skip invoices with charge < 25 cents; charge equal to 25 is retained.
5. Deduplicate each invoice’s events by eid. Keep the last event value while retaining the eid’s first insertion position.
6. Process deduplicated events in that order. Do not prioritize refunds or sort events by day.
7. Start active with refunded = 0.
   - void makes the invoice inactive, disabling subsequent refunds.
   - restore re-enables refunds; void is not permanent.
   - Neither void nor restore undoes earlier refunds.
8. Accept a refund only while active and when 0 <= event.day - created < 45. Age 45 is excluded; negative age is excluded.
9. Fees are refundable, so the refund ceiling is principal + fee_cents = charge.
   - If a refund exceeds the remaining unrefunded ceiling, reject the whole event.
   - A refund equal to the remaining ceiling is accepted.
   - Rejection does not undo prior refunds.
10. balance = charge - refunded.
11. Final status, in precedence order:
    - "VOID" if inactive, even if fully refunded.
    - "REFUNDED" if active and refunded == charge.
    - "OPEN" otherwise.
12. Sort retained invoices ascending by (created, id). Emit only id, charge, refunded, balance, status; monetary output values are cents.

Exceptions and boundaries
- Currency filtering and minimum-charge skipping remove invoices from output entirely.
- Deduplication replaces values without moving their original key positions.
- Refund-age checks apply to refunds, not void/restore.
- Earlier refunds survive later voids.
- A restore after a void can permit later eligible refunds.

Unresolved items
No current configuration choices remain unresolved.
The supplied contract does not specify the exact payload container schema, id/eid types or comparison rules, or invalid-input handling. Do not infer these from unrelated projects.