Retrieval-time money walls + capability keys (profit.read.own_sheet vs aggregate)¶
| Stage | Estimated |
|---|---|
| Status | Deferred |
| Design status | In review |
| Estimate | 2-3w (L) |
| Confidence | Low |
| Linear | PIN-151 ↗ PIN-375 ↗ |
| Linear status | Todo |
| Cycle | C15 |
| Design | Design ↗ |
| Linear epic | Cara AI & Automation |
| Module | Cara ↗ |
Priority: High
Scope¶
Enforces money walls at retrieval time, before the model ever sees the data: a response interceptor masks sensitive financial fields (cost basis, contract totals, vendor quotes, insurance exposure, incident financials) into 5 tier-based capability keys, replacing today's pass-through stub. Extends the same role-scoped retrieval to Compliance and Field-role Cara lookups once those modules ship. (Source: PIN-151, PIN-375.)
Acceptance criteria¶
- Financial responses masked server-side by role, via 5 tier capability keys spanning cost basis, contract totals, vendor quotes, insurance exposure, and incident financials
- Executive sees full financial data; PM-tier roles see only their permitted tiers; Field User sees no sensitive financials
- Masked fields hidden preemptively in list/grid views (e.g. Bid list, Estimate grid); mixed-access views render a blank cell instead of a value
- Automated check blocks a new sensitive field from shipping unmasked
- Cara retrieval surfaces Compliance issues and COI records to the Compliance role, and Daily Logs scoped to a Field user's assigned projects, once those modules exist
- Falls back to role-only scoping when per-project membership isn't available yet
Conor's comments¶
I believe Jonny is working on this.
Notes¶
DEV-BLOCKING foundation - sequence first. Wall enforced before model sees data. permissionFilter() is a pass-through stub today; PIN-151 mask unregistered
Open question for Conor¶
Confirm all PM-tier roles walled; ratify capability-key model