setup_payee
Status: Implemented | Module: enrollment
Set up payment information for a mileage-reimbursement driver. Supports direct_deposit (ACH — requires 9-digit ABA routing number and 4-17 digit account number) or check (paper checks to the address on file). IMPORTANT: Do NOT collect banking information unless the caller explicitly wants direct deposit; for check only name and address are required. Call AFTER enroll_driver.
Annotations
Section titled “Annotations”| Hint | Value |
|---|---|
| readOnlyHint | false |
| destructiveHint | false |
| idempotentHint | true |
| Field | Type | Required | Description |
|---|---|---|---|
session_id |
string | yes | Active session ID from verify_member |
payment_method |
string | yes | direct_deposit or check |
first_name |
string | yes | Payee first name (usually the driver) |
last_name |
string | yes | Payee last name |
account_type |
string | cond | checking or saving — required for direct_deposit |
routing_number |
string | cond | 9-digit ABA routing number — required for direct_deposit. Formatting (spaces, dashes) is stripped before validation. |
account_number |
string | cond | 4-17 digit account number — required for direct_deposit. Digits only after stripping formatting. |
tax_id_type |
string | no | ssn, ein, itin, or atin. Required when tax_id_number is supplied. |
tax_id_number |
string | no | Tax identification number (encrypted at rest) |
address_line_1 |
string | no | Payee street address |
address_line_2 |
string | no | Apartment, suite, or unit |
address_city |
string | no | City |
address_state |
string | no | 2-letter state code (normalized) |
address_postal_code |
string | no | ZIP code |
Output
Section titled “Output”| Field | Type | Description |
|---|---|---|
status |
string | success or error |
payee_id |
string | Payee UUID |
payment_method |
string | Echoed |
first_name |
string | Echoed |
last_name |
string | Echoed |
account_last_four |
string | Last 4 digits of the account number (direct deposit only) |
payee_status |
string | active on create |
idempotent |
bool | True when matched an existing payee by account fingerprint |
message |
string | Human summary |
guidance |
Guidance | Suggests set_booking_details next |
Validation
Section titled “Validation”routing_numbermust pass the ABA mod-10 checksum. Invalid routing numbers are rejected without retry. The error message never echoes the value.account_numbermust be 4-17 digits after formatting is stripped; all-digit enforcement.tax_id_typemust be one ofssn,ein,itin,atinwhentax_id_numberis supplied.- State codes are normalized to 2-letter form (e.g.
Virginia→VA).
See internal/app/enrollment/adapters/validation/ for the routing-number checksum implementation.
Compliance Notes (PCI + HIPAA)
Section titled “Compliance Notes (PCI + HIPAA)”- Account numbers and tax IDs are encrypted at rest using AES-GCM — see
internal/app/enrollment/adapters/crypto/. - Ciphertext and IV are stored separately; the plaintext is never persisted.
- Account last-4 and a stable fingerprint are stored alongside ciphertext to support last-4 display and idempotency matching without decrypting.
- The raw
routing_numberandaccount_numberinput values are overwritten with empty strings immediately after encryption to shrink the in-memory surface. - Error logs capture
session_idonly — never routing/account/tax numbers. - Audit entry
mcp.setup_payeemetadata carriesactionandfields_set(deterministic comma-separated list of FIELD NAMES:name,payment_method, and optionallyaccount_type,routing,account,tax_id,address). Values are never in metadata.
Idempotency
Section titled “Idempotency”When payment_method=direct_deposit, the use case fingerprints the normalized account number and looks up existing payees. A match returns the existing payee_id with idempotent=true — no new row is inserted.
Related
Section titled “Related”- Source:
internal/app/enrollment/usecases/setup_payee.go,internal/app/enrollment/register.go - Prerequisite: enroll_driver
- Next: set_booking_details