Attribution detail¶
Every number in Venturi is defensible because you can open it. Behind any attribution — a chargeback line, a team rollup, a single invocation — is an evidence drawer that shows exactly how Venturi reached that conclusion. When you disagree, you open a dispute; when the answer is genuinely wrong, you propose an audited override. This page explains all three.
This is the surface that makes a disputed chargeback never a black box.
The evidence drawer¶
From any attribution surface — a table row, a drill-down leaf, an export line you clicked through — open the evidence drawer to see the complete decision record for that result. It is the same record everywhere: the team rollup, the dispute, and the override all read from one source of truth.
The drawer shows:
| Field | What it tells you |
|---|---|
| Event | The invocation (event_id) and what was called — provider, served model, tokens, cost, timestamp. |
| Resolved owner | The team, project, identity, organization, and budget this invocation attributes to. |
| Stage origin | Which stage produced the result: stage_a (deterministic), stage_b (trained inference), or stage_c (allocation). |
| Output state | One of the six states — deterministically_resolved, strongly_inferred, bounded, ambiguous, unknown, not_identifiable. |
| Confidence | The coper score (0–0.95) and its band. |
| Evidence basis | The signals that supported the attribution — e.g. direct account binding, HRIS membership, deployment metadata, code ownership, telemetry correlation. |
| Candidate set | Where more than one owner was plausible, every candidate with its supporting evidence — Venturi preserves the disagreement rather than hiding it. |
| Selection rationale | Why the chosen owner won over the others. |
| Model version | When inference was involved, the trained model version that produced the result, linked to its tracked record. |
| Degradation state | Whether the result was produced normally or by a fail-open fallback. |
| Freshness | The time the underlying data was current as of. |
| Export eligibility | Whether this result is chargeback-ready (coper ≥ 0.80). |
Drilling down never loses the evidence
Drill from an organization total → team → service → invocation and the interpretation metadata travels with you at every level. The leaf shows the exact same decision record the dispute and override surfaces use — there is no point where a number loses its provenance.
Reading a contested attribution¶
When the output state is ambiguous, bounded, or carries a conflict, the drawer
shows the full candidate set side by side: each plausible owner, the evidence
that supports it, and what would have to change for Venturi to resolve it. This is
how you tell real ambiguity (a genuinely shared API key) from a fixable
data-quality gap (stale org data, an unmapped identity, conflicting CI/CD metadata).
For unknowns, see coverage & unknowns.
Reading an allocated (shared-service) line¶
Shared-service spend — a platform team's gateway, a common API key, a workload no
single owner clearly drives — resolves through allocation rather than to a single
point owner. For these stage_c lines the drawer shows you the allocation basis,
not just the headline owner:
| Field | What it tells you |
|---|---|
| Fractional split | The full N-way split across owners, with each owner's share. You see the whole distribution, not just the largest slice. |
| Producing signal class | The class of signal the split was computed from — e.g. proportional usage, headcount, deployment footprint — so you know what the shares are based on. |
| Allocation ceiling | Allocated and network-derived lines are confidence-capped at 0.70. The drawer states this plainly so you never read an allocated share as point-level certainty. |
Because the split is visible, you can contest the share itself — the fraction assigned to a given owner — separately from contesting which owner is largest. The two are different challenges, and the drawer keeps them distinct: you can accept that the platform team is the primary consumer yet still argue their 60% should be 45%.
No prompt or completion content¶
The drawer shows the metadata and evidence behind an attribution — never prompt or completion text. Venturi never stores message content, so it is never in the drawer.
Disputes¶
A dispute is the collaborative way to challenge an attribution without ever changing it by accident. Disputes are a first-class object: assignable, commentable, SLA-tracked, and bound to the attribution they question — but they never mutate it.
A dispute never changes attribution truth
Comments, mentions, assignments, and the dispute thread itself are metadata
about an attribution. The attribution record — its owner, coper, output
state, and stage origin — is byte-for-byte identical before and after a dispute.
The only action that changes attribution is a committed override (below), and
that change is an append, never a silent edit.
Opening a dispute¶
Anyone with view access to a result can open a dispute directly from its evidence
drawer. The dispute is pre-populated with the event_id, the full candidate set,
the output state, the coper, and the selection rationale, and is linked both ways
to the attribution record.
If an open dispute already exists on the same event, entity, or candidate pair, Venturi offers to link to it rather than fork a duplicate — so two people investigating the same number converge instead of colliding.
Working a dispute¶
A dispute moves through a clear lifecycle, with collaboration at every step:
graph LR
A[Open] --> B[Assigned]
B --> C[Under review]
C --> D{Resolve}
D -->|Override committed| E[Resolved · override]
D -->|Provisional accepted| F[Resolved · accepted]
D -->|Duplicate / invalid| G[Closed]
- Assign the dispute to a person or a role queue (for example, the FinOps review queue). Reassignment is audited and carries the SLA clock with it.
- Comment in a threaded discussion visible only to users with view scope on the dispute. Comments are editable by their author within a window, then append-only.
- Track the SLA — each dispute carries a configurable SLA clock that respects your business calendar; a breach raises an escalation exactly once, up the chain to the role queue and then to an admin until acknowledged.
The manual-review queue orders disputes by the canonical priority — highest spend first, then chargeback-eligible disputes, then highest uncertainty — so the work that matters most surfaces first.
Resolving a dispute¶
A dispute resolves one of three ways, and only one of them changes attribution:
| Resolution | What happens | Changes attribution? |
|---|---|---|
| Commit an override | A manual-override event is appended; the attribution is corrected. | Yes — by append |
| Accept the provisional | You accept Venturi's answer as-is. | No |
| Close as duplicate / invalid | The dispute is closed with a reference. | No |
Resolving via accept changes no graph edge. Resolving via override is the path described next. Both record the actor, timestamp, reason, and prior state.
Resolving non-point results¶
The hardest spend to attribute — bounded results where more than one owner is
plausible, and stage_c allocated lines split across several owners — is also the
spend you most need to defend internally. So a dispute on a non-point result gives you
resolution paths that match the shape of the answer, not just an all-or-nothing
accept:
- Resolve a bounded result. When the output state is
bounded, you can resolve the dispute to a specific candidate within the set — "it's this team" — or assert a fractional split across the bounded candidates — "60% this team, 40% that one." Either choice is recorded as a structured, append-only override and fed back as a strong supervision signal, so the engine learns your correction for next time. - Contest an allocated share. For a
stage_callocated line, you contest the split the drawer renders — the fraction assigned to an owner — on a path that is distinct from contesting which owner is largest. You can leave the primary consumer unchallenged and still correct the percentages, or challenge both. Either way the allocation ceiling of0.70still applies: an allocated line is never promoted to point-level confidence by a dispute.
Correct the share, not just the headline
A shared API key that splits 60/40 between two teams is a real, defensible number — but only if you can inspect and adjust the split. Venturi lets you contest the fraction itself, so the spend that is hardest to attribute is no longer the spend you can least defend.
Overrides¶
An override is the one human action that corrects an attribution — and it is designed to be permanent, auditable, and impossible to do unilaterally on high-stakes spend.
How an override is proposed and approved¶
An override is proposed by a user and approved by a separate person — separation of duties is enforced on the server and made visible in the UI:
You cannot approve your own override
The user who proposes an override can never be its sole approver. When the proposer opens the approval control, it is disabled with a clear explanation — "you proposed this; a separate approver is required" — rather than failing only at submit. A second principal with approval rights completes it. For overrides on large spend, a configurable threshold escalates from single-approver to dual-approver automatically. Rejection requires a reason code from an audited taxonomy.
What an override does — and how long it lasts¶
A committed override is an append-only correction. It is never an in-place edit:
- It survives graph rebuilds. When attribution is recomputed, your override is re-applied — it is never silently reversed by the next run.
- It is fully audited. Actor, approver, timestamp, reason code, and the prior state are written to the immutable audit log.
- It can be revoked through the same audited, separated-duty workflow — which is itself another append, preserving the full history.
This is why a corrected number stays corrected, and why an auditor can always see both what the engine concluded and what a human changed, with the reason.
Seeing the effect of your override¶
The moment you commit an override, Venturi shows you an effect summary in the same session — so a correction never disappears into the audit log with nothing to show for it. You acted, and you immediately see what changed:
| The summary tells you | What it means |
|---|---|
| Attributions changed | The count and total spend of currently-materialized attributions that moved as a direct result of your correction — so you can confirm your chargeback number is actually fixed. |
| Time-basis treatment | Exactly how historical records were handled: whether they were re-attributed to the corrected owner or preserved at their original event-time owner. This is always stated explicitly — never silently chosen for you. |
| Captured for the future | Confirmation that your correction was recorded as a governed signal the engine learns from, so the same misattribution does not recur. |
The summary reports effects — it never rewrites history
The effect summary describes how your override flows through the currently-materialized view. It composes the same append-only, no-mutation guarantees as everything else on this page: prior states are preserved, the correction is an append, and the summary simply makes its reach visible. Seeing "47 attributions, $128k re-attributed" is how you know the fix landed — without it, a correct override would feel ignored.
Locking and legal hold¶
An admin or a legal-gated actor can lock an override (or every object scoped to a subject or case) for audit or legal hold. A locked object rejects edits, archival, and deletion, and is excluded from retention purges until released. Lock and release are fail-closed, and tenant-wide holds require two actors.
Custom fields and templates¶
Admins can add typed custom fields (text, number, enum, date, or entity-reference) to disputes and overrides — for example a "BU code" enum — which then appear as search facets and export columns. Reusable intake templates (a standard dispute form, a standard override request) pre-populate new objects so your team captures the right context every time.
Who can do what¶
| Action | Who |
|---|---|
| Open and comment on a dispute | Any user with view access to the attribution |
| Resolve a dispute by accept / close | The dispute owner or an admin |
| Propose an override | An engineer (or higher) within scope |
| Approve an override | A separate admin (or threshold-required second approver) |
| Lock / legal-hold | An admin or legal-gated actor |
See roles & RBAC for the full matrix.
Next steps¶
- Use Coverage & unknowns to resolve the unknowns that disputes often start from.
- Use Confidence and evidence to learn what the scores, states, and evidence basis mean.
- Use The HRE pipeline to see the three stages whose decisions the drawer records.
- Use Audit logs to find where every override and resolution is recorded immutably.