Skip to main content

Proposal: Payout Automation — award → paid → receipt

Status — proposed 2026-07-04, not yet built

Owner: Guido · drafted with Fable. Depends on the shipped beneficiary-address collection in the contributor portal (2026-07-02: address capture, backfill banner, audited ops export — see Data Model). The award trigger is designed to be fed by the Reward Economy quests-pay-cash model once that ships; until then awards are entered by ops.

Problem

Paying a contributor is manual end to end. Who-is-owed-what lives outside any system; ops keys each recipient into Altitude by hand; nothing records that a payment was submitted, succeeded, or failed; no receipts are issued; and the €4,000/12-month operating cap plus the contributor's €5,000 prestazione-occasionale ceiling are enforced by memory, not by code.

Detail collection is already solved: the portal collects beneficiary name split

  • full address with the IBAN, and npm run ops:export-recipients produces an Altitude-ready list with full IBANs, missing-data flags, and per-call audit logging.

Verified current state (2026-07-04)

  • 19 unique confirmed IBANs; address backfill in progress.
  • The April 2026 schema already models the whole pipeline — payout_requests, payment_batches, payments, receipts, cap_snapshots, exceptionsand every one of those tables is empty. The earn→milestone machinery (reward_milestones, playroll_time_ledger, contributor_milestone_unlocks) has never been written to; the Reward Economy proposal replaced the hours→cash ladder with quests-pay-cash, which is the future source of awards.
  • Rail: Altitude (Squads business banking). No public API. Team approval thresholds exist in-app.
  • Wise Business API (verified against Wise docs, 2026-06 revision): create recipients, create single/batch transfers, fund via API from a US business account, transfers#state-change webhooks, sandbox. Their no-code batch tool takes a CSV of up to 1,000 payouts. This is the recommended Phase 2 executor; payment_batches.provider already includes 'wise'.
  • Grid (Squads developer platform): stablecoin accounts with fiat on-ramp. Third-party EUR SEPA payouts are unconfirmed — open question with Squads. Not on the critical path.

Design

One state machine over the existing tables. All transitions are service-role-only SECURITY DEFINER RPCs, each writing an audit row. Contributors gain no new write surface.

award (ops cmd; later: quest completion)
└─ compensation_items('available') + payout_requests('requested')
└─ no confirmed+complete payout method → 'needs_payout_method' + nudge
└─ contributor completes portal form → auto-heals to 'requested'
approve (ops cmd; €4k rolling-cap check; batch ceiling)
└─ payment_batches('approved') + payments('approved')
execute
├─ Phase 1: per-batch export in Altitude field order → ops keys in → mark-paid (requires bank reference)
└─ Phase 2: Wise API — recipient create → transfer create → fund → webhook flips paid
mark-paid / mark-failed
└─ cascades: compensation item, request, batch, receipt(draft), cap snapshot; failures → exceptions

Key properties: idempotent awards (unique key), one open request per contributor, mark-paid always traces to a bank-side reference, receipts generated per payment (held in draft until the ricevuta template is approved), immutable audit log, "IBAN changed since last payment" flag in the approval queue.

Phasing

  1. Phase 1 — no APIs, ~1–2 days: migration (RPCs + audit table + 'altitude' in the provider check) + payout CLI (award/approve/export/mark-paid/mark-failed/status). Carries ~€100k of volume safely because Altitude remains the vault: the automation is bookkeeping and assist; money authority never leaves the bank UI.
  2. Phase 1.5 — zero code: Wise Business account + --wise flag on the export emitting Wise's batch-CSV template. Upload, fund once, done.
  3. Phase 2 — Wise API: executor + webhook reconciliation replace the paste step. Swappable for Grid later if Squads confirms third-party EUR SEPA payouts.

Open questions

  1. Source of truth for the current Pioneer amounts owed (seeds the first award --csv).
  2. Nudge/receipt email channel: manual DM now; SMTP-via-edge-function as the built path.
  3. Ricevuta template sign-off (Ryon) before receipts auto-send.
  4. Squads/Grid: third-party EUR SEPA payouts available? (Phase 2 alternative only.)