Disbursement Authorization Controls

Approval tiers, a fresh authenticator code before money moves, a three-business-day wait on a changed vendor bank, an email to the board on every payment, and the FADR artifact that records the chain. How CommunityPay ensures every outgoing payment is authorized, documented, and verifiable.

11 min read Governance & Controls Published May 22, 2025

Every outgoing payment in CommunityPay passes through a multi-layer authorization system before funds move. This page describes the approval workflow, the enforcement checks, and the evidence artifact (FADR) that documents the complete authorization chain.

The Authorization Stack

Disbursement authorization operates in three layers:

Layer 1: Enforcement Guards

Before any payment can proceed, it passes through the bill_payment flow in the EnforcementDispatcher. The flow evaluates 14 guards in sequence, and a fifteenth, connect_balance, on the Stripe payout rail. The dispatcher stops at the first block; every guard that runs before it records its answer:

Guard What It Checks
balance Journal entry debits equal credits
closed_period Payment is not posting to a closed accounting period
fund_segregation Payment draws from the correct fund (operating vs. reserve)
fund_consistency The cash leaving belongs to the fund the entry is posted in
trust_segregation Trust funds are not commingled with operating funds
subledger Every bill, invoice, vendor, and unit the posting references exists and belongs to this association
invariant The posting meets the invariants of its transaction type: line count, required references, allowed account types
l5_exclusion The association carries no active bind-block exclusion; an active one refuses every posting
fund_eligibility An expense account posting to a reserve fund is marked reserve-eligible, or the posting carries a stated reserve override reason
bill_payment The payment spends a live approval bound to this amount, vendor and fund — and, on the Stripe rail, the payout destination approved with them — and no payment already exists. On the Stripe rail a changed vendor bank has also served its waiting period, and no override can shorten it
vendor_risk For a vendor linked to a contractor licensing record: debarment, license status and expiry, insurance expiry, and active contractor strikes
disbursement_compliance The approval satisfies the state's board-approval, reserve fund, and dual signature rules
connect_balance On the Stripe rail: the provider balance can fund the payout, its snapshot is current and for this account, and the payment is within the transfer limit
fund_policy The paying fund's own board policies permit the payment: the expense accounts the bill charges, and the board vote or approver seat a payment at or over a policy's amount requires
loan_covenant No debt covenant is breached by the disbursement

If any guard fails, the payment is blocked and an EnforcementDecision with outcome BLOCK is recorded. A guard that can be overridden needs a recorded board override, and writing one takes a fresh authenticator code. The blocking guard, its failure code, and the reason are captured.

Layer 2: Approval

The bill is approved before it is paid, not after. The approval is a record: who approved, at which level, when, under which settings, and what the approval covers — the amount, the vendor, the fund, and, on the Stripe payout rail, the vendor's payout destination. The bill_payment guard reads that record at payment time. A payment whose bill holds no live approval, or whose amount, vendor or fund is not the one approved, is refused, and so is a Stripe payout to a destination other than the one approved. The refusal is an enforcement decision like any other. On the manual pay-bill door the destination is not part of the posting; what holds it there is that changing a vendor's bank details uses up the approvals of that vendor's unpaid bills and sends them back for approval.

The rule behind every approval and every payment:

  • Authority comes from an accepted membership in that association. A platform staff account with no membership there approves nothing and pays nothing.
  • One person gives at most one approval per request.
  • Levels are fixed when the request opens, so changing a tier afterwards does not re-judge a bill already submitted.
  • An association can require that the person who pays be neither the submitter nor an approver. That is judged when the payment happens.
  • Reversing a payment consumes the approval it spent. The bill is approved again before it can be paid again.

Each approval step records:

  • Who approved (or rejected)
  • When they acted
  • What they saw at decision time (amount, vendor, bill details)
  • Any notes or conditions attached to the approval

Layer 3: Vendor Standing

For a vendor linked to a contractor licensing record (Washington and Oregon records), the vendor_risk guard reads the stored record before the payment posts:

  • Debarment: a debarred contractor is blocked.
  • License: a suspended or revoked license is blocked, and so is a license past its expiry date.
  • Insurance: insurance past its expiry date is blocked.
  • Strikes: active contractor strikes block the payment.

A vendor with no link passes the guard, and the decision records that the vendor could not be evaluated. Bond and W-9 status are recorded on the vendor record; the guard does not read them. The guard reads the record on file, and contractor records are not refreshed on a schedule at present. A block here is overridable with a documented board override.

Controls Around the Money

The guards and the approval decide whether a payment may post. These controls decide who can move money, and where it can go.

  • A fresh authenticator code before money moves. Paying a vendor by transfer, approving a bill, changing a vendor's bank, changing the transfer limit, writing an override, and changing who may approve and pay each ask for a code from the authenticator app, or a recovery code, within the last ten minutes. Paying several bills in a row needs one confirmation. A text-message code never confirms a money action.
  • A changed vendor bank waits. A bank that replaces an earlier one is paid on the Stripe rail only after three business days. A different board member can end the wait early, after calling the vendor at a number the association already had, with a fresh code and the association's bank PIN. A later change of that vendor's bank waits again.
  • A transfer limit. On the Stripe rail no single vendor payment, and no 24 hours of them together, may exceed the association's buffer target, which is $5,000 where none is set. A payment over the limit is refused with a recorded decision. Changing the limit asks for a fresh code.
  • The vendor's bank is attached at its first payment and paid by its stored identifier. It comes off the processor after the payout settles plus seven days — at once if the vendor is deactivated or its bank changes. The rail refuses an inactive vendor.
  • Every vendor payment sent by transfer and every top-up from the association's bank is emailed to the whole board.
  • A bounced payout reverses its entry and reopens the bill. Nothing stays marked paid that was not.
  • One pinned payout bank. A vendor's bank can never be it. Changing it takes two board members, one to ask and a different one to confirm with the bank PIN and a fresh code. The board is emailed, and the first payout to the new bank is held until a person releases it.
  • Money abilities start off, except for an association's first officer. Paying vendors, vendor bank details, the transfer limit, top-ups, and the payout bank are granted per admin, only by someone who holds the ability, with a fresh code and an email to the board.
  • Reserve money leaves the reserve only by a board-approved transfer. A reserve bill is paid online only after that transfer has posted.
  • Emailed invoices never pay themselves. The invoice inbox submits for approval, drafts, or holds; it never approves and never pays.

Approval Configuration

Each association configures the first three:

Setting Description
Bill approval tiers Bands of amounts, each naming the levels that must approve a bill in that band. The bands cover every amount, and a bill belongs to exactly one. With no tier, one system default applies: one level, any board member or admin
Self-approval Whether the person who submitted a bill or transfer may also approve it. On by default
Separate payer Whether the person who pays must be someone other than the bill's submitter and approvers. Off by default, and judged when the payment happens

The fourth input is not configured by the association. The board-approval cap and the dual signature threshold that disbursement_compliance reads are resolved from the legal corpus for the association's state, and where the corpus holds no row for that state the guard applies a platform floor in code.

Every change to a tier or to either setting writes an immutable record naming who made it, and the board is notified. The settings in force are part of the policy snapshot on every enforcement decision, so a decision made last year reads against the settings that were in force then, not today's.

The FADR Artifact

The Funds Authorization & Disbursement Record (FADR) is the evidence pack that documents the complete payment authorization chain.

What the FADR Contains

Each FADR captures:

Payment Identity

  • Reference number, type, status, amount, execution date
  • Payment method and gateway used

Vendor Identity

  • Vendor name, tax ID (masked), address
  • Payment method on file
  • Contractor licensing record link (if applicable)

Approval Chain

  • Every actor in the approval sequence
  • Their action (SUBMITTED, APPROVED, REJECTED, POLICY_OVERRIDE)
  • Timestamp of each action
  • Notes or conditions attached

Policy Snapshot

  • Approval thresholds active at decision time
  • Required number of approvers
  • Any overrides applied and their justification

Journal Entry

  • The balanced journal entry created by this payment
  • All lines with account codes, fund assignments, debit/credit amounts

Bills Paid

  • Every bill covered by this payment
  • Bill amounts, vendors, dates, and approval status

Vendor Compliance

  • The vendor's standing at payment time, from the last check on record at or before the payment: compliance status, certificate of insurance status and expiration, license status and expiration
  • The number of compliance alerts open when the payment posted
  • Where the vendor is not linked, or no check was on record by then, the packet says the standing is not established and does not verify it

Risk Assessment

  • Automated risk flag detection
  • Flags for: override usage, a payment of $50,000 or more, vendor compliance gaps, and a payment with no linked journal entry

Verification Status

Each FADR receives a verification status:

Status Condition
VERIFIED The approval chain is complete and recorded, the approvals the guard required are on the record, the entry balances, no override was used, and no high or critical flag is raised
NEEDS_REVIEW A high flag, an approval the record cannot place, approval levels the record cannot state, a vendor standing not established, fewer approvers than required, an override used, a reversed payment, or an entry that is missing or does not balance
FLAGGED A critical flag: the vendor had critical compliance issues at payment time

Content Hash

The FADR evidence snapshot is hashed with SHA-256 using canonical JSON serialization. This hash enables independent verification that the FADR has not been modified after generation.

Version Chain

If a FADR is regenerated for the same scope, the new version links to the previous version via previous_packet_hash, creating a tamper-evident chain.

What This System Proves

For any payment in CommunityPay, the disbursement authorization system can answer:

  1. Was the payment authorized? — The approval chain shows who approved and when
  2. What rules governed the approval? — The policy snapshot shows the thresholds active at decision time
  3. Did the vendor meet compliance requirements? — The vendor compliance section shows the standing on record at payment time, or says it could not be established
  4. Was the journal entry correct? — The journal entry lines show the balanced posting with fund allocations
  5. Were any exceptions made? — Override records and risk flags show any deviations from standard process

These answers are not reconstructed from system state — they are frozen at decision time and stored in the immutable evidence snapshot. The FADR for a payment made six months ago reflects the exact state of the system at that moment, not the current state.

CARI Integration

Disbursement patterns and authorization effectiveness feed into the CARI Payment Behavior sub-score, which carries a 15% weight in the composite score. Prevented losses from guard blocks, dispute rates on completed payments, and collection rates on authorized disbursements are key signals. The ratio of override usage to standard authorization flow is also factored into the scoring computation.

For published methodology and component weights, see CARI Methodology and Scoring Framework.

How CommunityPay Enforces This
  • Every vendor payment passes through the EnforcementDispatcher and is evaluated by the 14 guards the manifest selects for the bill_payment flow, and by a fifteenth on the Stripe payout rail
  • Board-set approval tiers covering every amount, with a system default of one board approval where no tier applies
  • The payment spends a live approval bound to the bill's amount, vendor and fund, and on the Stripe rail to the payout destination approved with them; change any of them and the bill is approved again before it can be paid
  • A fresh authenticator code, within the last ten minutes, before a vendor is paid by transfer, a bill is approved, a vendor's bank is changed, or an override is written; a text-message code never confirms a money action
  • A changed vendor bank waits three business days before the rail pays it; a different board member can end the wait after calling the vendor at a number the association already had, with a fresh code and the association's bank PIN
  • On the Stripe rail no single vendor payment, and no 24 hours of them together, may exceed the transfer limit, which is the association's buffer target ($5,000 where none is set)
  • Every vendor payment sent by transfer and every top-up from the association's bank is emailed to the whole board
  • Changing the association's payout bank takes two board members, and the first payout to the new bank is held until a person releases it
  • FADR evidence pack captures the complete authorization chain from bill creation through payment execution
  • Policy snapshots frozen at decision time — approval threshold changes do not retroactively affect past decisions
  • Vendor standing at payment time recorded in the FADR, or stated as not established where no check was on record
  • Risk flags auto-detected: override usage, large payment threshold, vendor compliance gaps
Login