# Research: Finding Ownership Semantics Clarification

**Date**: 2026-04-20  
**Branch**: `219-finding-ownership-semantics`

## Decision 1: Reuse the existing finding owner and assignee fields as the only responsibility truth

- **Decision**: Keep `findings.owner_user_id` and `findings.assignee_user_id` as the sole persisted responsibility fields and derive any responsibility-state wording from them.
- **Rationale**: The current model, workflow service, migrations, and tests already support independent owner and assignee assignment. The spec problem is semantic ambiguity, not missing persistence.
- **Alternatives considered**:
  - Add a new persisted responsibility status column. Rejected because the state is directly derivable from existing nullable fields.
  - Introduce a separate responsibility aggregate/service object. Rejected because one resource and one model can express the needed truth without adding a new layer.

## Decision 2: Treat assignee-without-owner as an accountability gap, not a healthy assigned state

- **Decision**: Use a derived responsibility contract where owner presence determines accountability. `owner != null && assignee == null` is `owned but unassigned`; `owner != null && assignee != null` is `assigned`; any `owner == null` case is an accountability gap, even if an assignee exists.
- **Rationale**: The spec defines owner as accountable for the outcome and assignee as actively executing work. Existing resolver logic already treats missing owner or missing assignee as follow-up needing attention.
- **Alternatives considered**:
  - Treat any assignee as `assigned` even without an owner. Rejected because it hides the exact accountability gap the feature exists to surface.
  - Introduce a fourth persisted state family. Rejected because the business consequence is presentation and next-action guidance, not new workflow routing.

## Decision 3: Keep exception owner explicitly separate from finding owner

- **Decision**: Preserve `finding_exceptions.owner_user_id` as a distinct governance concept and label it only as `Exception owner` when shown in a finding context.
- **Rationale**: The current resource already surfaces exception owner separately, and the spec explicitly calls out the risk of accepted-risk flows reintroducing ambiguity under a second `Owner` label.
- **Alternatives considered**:
  - Collapse exception owner into finding owner language. Rejected because it would blur responsibility for the finding with responsibility for the exception artifact.
  - Rename finding owner around exception flows only. Rejected because local relabeling would increase rather than reduce semantic drift.

## Decision 4: Keep the implementation local to the existing findings resource and current workflow services

- **Decision**: Make the semantics change in `FindingResource`, with only small supporting adjustments in `Finding`, `FindingWorkflowService`, `FindingExceptionService`, and `FindingRiskGovernanceResolver` if wording or derived next-action copy needs alignment.
- **Rationale**: The current UI already displays owner, assignee, and exception owner. The gap is where those semantics are explained, prioritized, and tested.
- **Alternatives considered**:
  - Add a new presenter or explanation layer for responsibility semantics. Rejected because a local derived helper is sufficient and aligned with the constitution’s anti-layering bias.
  - Add a dedicated responsibility page. Rejected because the findings list/detail surfaces are already the operator decision context.

## Decision 5: Use focused Pest feature + Livewire coverage, not browser or heavy-governance tests

- **Decision**: Cover the feature with focused findings resource and workflow feature tests, including explicit tenant-context setup and Filament routing discipline.
- **Rationale**: Existing tests already prove tenant-member validation and row-action behavior. The missing coverage is list/detail semantics and owner-only versus assignee-only feedback.
- **Alternatives considered**:
  - Browser tests. Rejected because the behavior is visible and provable through current Filament Livewire test patterns.
  - Unit-only tests. Rejected because they would miss the operator-facing semantics that motivated the spec.

## Decision 6: Preserve current tenant-panel and canonical-admin context rules during testing

- **Decision**: Keep tenant context explicit in tests and use explicit panel selection for tenant-route assertions when necessary.
- **Rationale**: Repository memory shows two relevant pitfalls: tenant-scoped Filament list pages can lose context on later Livewire interactions, and `Resource::getUrl(..., tenant: $tenant)` defaults to the admin panel unless `panel: 'tenant'` is passed.
- **Alternatives considered**:
  - Rely on implicit panel resolution in tests. Rejected because it can produce false redirects to `/admin/choose-tenant` instead of the intended authorization result.
  - Broaden shared fixtures to always set tenant context. Rejected because the constitution prefers opt-in context rather than expensive defaults.