Vendors & Liabilities
Vendors are external contractors or agencies tracked in VERA. Liabilities are fixed payment commitments to those vendors.
Vendor users
A vendor is a user with employment_type = "vendor".
add_user name="Dev House X" employment_type="vendor"Vendor users are like regular users in the system — they appear in list_users, can be allocated to projects. The difference is:
- Nobody records time for them — vendor users don't message the bot themselves, and their hours and cost come from their liability
- Cost is typically governed by a liability rather than an hourly rate
- Revenue is the same as direct labor — hours × billing_rate
Liabilities
A liability is a fixed payment commitment to a vendor on a specific project, or to a contractor (see A contractor on a fixed price below).
Example: "We agreed to pay Dev House X $5,000 to build the authentication module on Project Rambo."
This is recorded as a liability with:
vendor_user_id— Dev House X's user IDproject_id— Project Ramboagreed_amount— $5,000agreed_hours— 80 (the contracted scope in hours)description— "Authentication module development"
Why liabilities exist
Without a liability, VERA calculates vendor cost as hours × hourly_cost. But for fixed-fee vendor engagements, that's wrong — you've agreed to pay $5,000 regardless of how many hours are logged.
A liability overrides the hourly calculation entirely. When a liability is active for vendor X on project Y, the cost for that vendor on that project is agreed_amount, not hours × rate. The two methods are never mixed.
Vendor hours and the project budget
agreed_hours captures the contracted scope in hours. Because vendors don't log time themselves, VERA cannot know their actual pace — so it assumes even delivery from the liability creation date to the project deadline:
implied_hours_today = agreed_hours × (days_elapsed / total_days)This implied figure is added to the team's logged hours when computing budget burn, health status, and proactive alerts. The project deadline is the 100% mark; at the deadline, all agreed_hours count in full. A cancelled liability contributes zero implied hours.
On a retainer period, the period's own window takes the place of creation-to-deadline: the liability accrues from the period's first day to its last, so one added to next month's period in advance accrues nothing until that period opens. Its implied hours count toward the period's hours, revenue and pace, and roll up into the retainer.
Both the agreed_hours value and the accrued implied_hours_to_date appear in the list_liabilities response. The project's deadline must be set before a liability can be created; for a retainer period, its start and end must be set instead. A sprint of an Agile engagement cannot carry a liability.
A T&M project can't carry a liability, a vendor's or a contractor's. On T&M each recorded hour is the invoice line, and a liability records no hours, so it could only ever be unbilled cost; a fixed fee belongs on a Fixed Price project. VERA refuses to add one there, and refuses to change a project to T&M while it has an active one (cancel the liability first). Liabilities made on a T&M project before this rule keep accruing, and can still be edited and cancelled; the project's Liabilities card appears only while it has one, and offers no Add control (issue 2623).
Revenue follows the calendar too
On a Fixed Price project or a retainer period, a liability's implied hours count toward completion, so the revenue they earn builds up on the same calendar as the liability's cost. A $5,000 subcontract on a $25,000 job earns and costs evenly across its dates. On T&M, revenue is still recorded hours × billing rate, so a liability there could only affect cost; that is why new ones are refused on T&M (issue 2623), and one made earlier counts its cost and hours with no revenue.
A contractor on a fixed price
A liability can also go to a contractor: someone paid a fixed price for a piece of work, who still records their time. Only on a Fixed Price project or a retainer period, where revenue follows hours against a budget; never on T&M, where each recorded hour is billed. The owner adds it on the project's (or the period's) Liabilities card and picks a task: VERA makes the contractor an envelope to record against, labelled with the liability's description, unless they already have one there. They record time exactly as before.
Recorded time is reference only. On a Fixed Price project or a retainer period, any time recorded by a person holding an active liability on that project (a contractor, or a vendor whose time someone records) counts toward none of the project's hours, revenue, cost or pace: the liability's implied hours and cost stand for it, so nothing is counted twice. The hours stay on their envelope, the Delivery tab, the Time entries list and their own pages, for comparing with the agreed hours afterwards. While the liability is active they record against one envelope on that project; a second is refused.
The liability and its envelope are one. When VERA makes the envelope for the liability, the two go together: cancelling either cancels both, the envelope's hours are the agreed hours (changing either changes both), and its label is the liability's description. Only an owner can do any of that, since it changes the liability; a manager can still set the envelope's task, window and weekly plan. An envelope cancelled with its liability stays cancelled; add a new liability to start again. Each one's ID names the other: envelope 1 reads 1(LIA.2) and its liability 2 reads 2(ENV.1), linked where you can open the other. Re-up and Duplicate project copy the pair as a pair. An envelope the contractor already had before the liability is not part of it, and is left alone.
Seeing every vendor's work
Staffing → Vendors lists every vendor, and every contractor holding a liability, one per row. Each row opens like an accordion: closed, it shows how many active liabilities they hold and their hours (agreed, built up to date, and still to come); open, it lists each liability with its project, description and agreed amount. A vendor with none still appears, marked "No active liabilities". Vendors never appear in Staffing → Capacity, which is for people whose hours VERA plans week by week, so this tab is where their workload shows. Managers see only the liabilities on projects they are PM of, as on the Liabilities tab.
Liability lifecycle
create_liability → active
↓
cancel_liability → cancelled (not deleted)Cancelled liabilities are kept for audit trail. When listing liabilities, filter by status = "active" to see open commitments only.
Permissions
| Action | Owner | Manager | User |
|---|---|---|---|
| Create liability | ✅ | ❌ | ❌ |
| View liabilities | ✅ (all) | ✅ (own projects) | ❌ |
| Cancel liability | ✅ | ❌ | ❌ |
P&L cost rule (vendor summary)
For vendor X on project Y:
If active liability exists:
cost = liability.agreed_amount
Else:
cost = hours_logged × hourly_cost (from Rate History, effective on entry date)This rule is applied when calculating project cost and margin in generate_monthly_report and the reporting sheet's financial tabs.
Common vendor workflow
- Add the vendor:
add_userwithemployment_type="vendor" - Create a liability:
create_liabilitywith the agreed amount, contracted hours, and description — the project must have a deadline set, or, for a retainer period, a start and end - PM logs hours:
log_timewith the vendor's user ID — this tracks delivery against the engagement (optional but recommended) - View cost: The liability's
agreed_amountappears as cost in financial reports, regardless of hours logged - Budget burn: The vendor's
agreed_hoursaccrue linearly against the project budget — no manual entries needed for the hours story to stay accurate
If the engagement grows beyond the original liability, cancel the old one and create a new one with the updated amount.