5.4 KiB
5.4 KiB
Research: Stored Reports Surface v1
Date: 2026-05-06
Branch: 277-stored-reports-surface
Decision 1: Use one tenant-panel Filament resource with list and view pages
- Decision: Implement the new surface as one tenant-scoped Filament resource with a register and a read-only view page.
- Rationale: The repo already uses tenant-panel Filament resources with clickable-row inspection and infolist-style view pages for read-only registry surfaces. That keeps the slice inside the current UI contract, keeps Livewire behavior native, and avoids a bespoke report-view shell.
- Alternatives considered:
- Custom dashboard page or widget-only viewer: rejected because it would create a parallel navigation and interaction model for a standard read-only registry surface.
- Edit-page-as-view workaround: rejected because the constitution requires inspection surfaces to use view/infolist semantics rather than disabled edit forms.
Decision 2: Reuse StoredReport and ArtifactTruthPresenter instead of creating new lifecycle truth
- Decision: Keep
StoredReportas the only persisted truth and reuseArtifactTruthPresenter::forStoredReport()for current versus historical retained state. - Rationale: The presenter already computes retained lifecycle truth by comparing the current row to the latest same-family row for the tenant. A second status column, mirror record, or new presenter layer would duplicate truth the repo already has.
- Alternatives considered:
- Persist a
currentflag or second lifecycle column onstored_reports: rejected because current versus historical is already derivable from existing rows. - Introduce a new stored-report-specific presenter or envelope system: rejected because
ArtifactTruthPresenteralready covers stored reports.
- Persist a
Decision 3: Add explicit permission_posture.view instead of piggybacking on unrelated capabilities
- Decision: Introduce one bounded
permission_posture.viewcapability alongside the existingentra_roles.viewcapability. - Rationale: The spec requires family-aware browse and detail visibility. Reusing
provider.view,review_pack.view, orevidence.viewwould blur ownership between the stored-report surface and downstream consumers. - Alternatives considered:
- Reuse provider or evidence capabilities: rejected because the stored-report surface would become coupled to unrelated read paths.
- Introduce one generic
stored_report.viewcapability: rejected because the repo already has two concrete families with separate product meanings, and family-aware filtering is part of the feature value.
Decision 4: Support exactly two family summary branches and keep all other families out of v1
- Decision: Render explicit summary branches only for
permission_postureandentra.admin_roles, and keep any unexpected report family entirely outside v1 browse and detail scope. - Rationale: The repo has exactly two concrete stored-report families today. The narrowest correct implementation is explicit presentation for those families only. A local catch-all renderer would still need an authorization story and would widen the surface contract beyond the two repo-real families.
- Alternatives considered:
- Generic report-schema registry or plugin renderer: rejected because two concrete cases do not justify a framework.
- Local catch-all renderer for unexpected families: rejected because it widens the browse/detail contract without a bounded authorization story.
Decision 5: Canonical drilldown stays on the one confirmed widget seam
- Decision: Make the stored-report detail route the canonical drilldown target for
AdminRolesSummaryWidgetonly. - Rationale: The widget is the clearest current repo-real missing launch point. The codebase does not currently expose broad Filament proof links to stored reports, so the package should not invent new local report cards or pseudo-view links just to claim convergence.
- Alternatives considered:
- Widget-only link with no register: rejected because it would leave stored-report browsing fragmented.
- Add new stored-report links to every evidence or review surface up front: rejected because repo truth does not currently show broad operator-facing stored-report launch affordances there.
Decision 6: Keep proof in focused feature tests and skip browser by default
- Decision: Plan feature coverage for register behavior, entitlement behavior, detail presentation, and widget drilldown, with no default browser lane.
- Rationale: The surface is native Filament list and view behavior plus a widget link. The main risks are authorization and disclosure rules, not browser-only choreography.
- Alternatives considered:
- Browser smoke as a default requirement: rejected because the slice does not introduce a custom interaction model.
- Large unitized presentation layers: rejected because that would create indirection just to make testing easier.
Final Research Outcome
- One native tenant-panel Filament resource is the narrowest correct surface shape.
- Existing stored-report truth and artifact-truth lifecycle semantics are sufficient; no new persistence or lifecycle framework is needed.
permission_posture.viewis the only new capability required.- Summary rendering stays explicit for the two repo-real families and avoids a registry.
- Canonical drilldown starts and ends in v1 with the admin-roles widget seam.
- Focused feature tests are the honest default proving path.