6.3 KiB
Phase 0 Research: Shared Detail Micro-UI Contract
Research Inputs
- Repository truth from current hosts and tests for
verification-report-viewer, onboarding verification, tenant verification widget,normalized-settings,policy-settings-standard, andnormalized-diff - Filament v5 notes in
docs/research/filament-v5-notes.md - Version-specific Filament documentation for custom fields, custom infolist entries, render hooks, and testing
Decision 1 — Verification Report should stay Blade-rooted and support-backed
Decision: Standardize the Verification Report family by extending the existing VerificationReportViewer support seam and one shared Blade root, instead of introducing a new Livewire component or a custom Filament entry class.
Rationale: The family already spans three host classes: an infolist-style run detail, a form ViewField inside onboarding, and a widget include. Filament custom entries are reusable, but they are still infolist-specific. Filament custom fields are form-specific. A new Livewire component would impose a heavier lifecycle and more new surface area than this feature needs. The existing support seam already owns report extraction, fingerprinting, and previous-run lookup, which is the right narrow base.
Alternatives considered:
- Create a custom infolist entry for verification: rejected because onboarding and widget hosts would still need separate structural ownership.
- Create a dedicated Livewire verification viewer: rejected because it imports new lifecycle complexity for a mostly read-only, DB-only surface.
- Keep the onboarding fork and only restyle it: rejected because the drift is structural, not cosmetic.
Decision 2 — Onboarding-specific assist and acknowledge behavior must remain host-owned slots
Decision: Treat assist, acknowledge, refresh, and technical-details triggers in onboarding as explicit host-owned variations of the verification family, not as a second verification UI contract.
Rationale: The onboarding wizard legitimately owns interactive workflow actions and different no-run or in-progress framing. The shared family should own summary, tabs or view zones, issues, passed checks, diagnostics, and unavailable behavior. This respects the spec’s rule that hosts may extend actions and placement without redefining the family core.
Alternatives considered:
- Move assist and acknowledge logic into the shared core: rejected because those actions are wizard-specific and would leak workflow behavior into unrelated hosts.
- Leave onboarding fully separate: rejected because it preserves the existing duplicate tab contract and duplicated grouping logic.
Decision 3 — Normalized settings must converge under one family wrapper with explicit subtypes
Decision: Standardize normalized settings through one family-owned wrapper that explicitly supports at least two subtypes: settings-catalog table rendering and standard block or key-value rendering.
Rationale: PolicyResource and PolicyVersionResource currently choose between normalized-settings and policy-settings-standard at the host level. That means the host, not the family, owns warnings, wrapper titles, empty state, and subtype selection. The repo already proves the two subtypes are real. The narrowest fix is not to flatten them, but to put both behind one family wrapper.
Alternatives considered:
- Keep both views and only document when to use each: rejected because the host-level fork remains the same.
- Force every settings subtype into one totally uniform table: rejected because the domain richness and script-oriented rendering would be weakened.
Decision 4 — Normalized diff must own unavailable and partial-state semantics
Decision: Move unavailable, partial, and zero-diff behavior into the normalized diff family contract instead of leaving those semantics to individual hosts.
Rationale: FindingResource currently shows a host-owned unavailable text entry before the shared diff view, while PolicyVersionResource simply renders the diff view. This is the clearest current evidence that the same content concept does not yet own its own availability rules. The family should own these states so equivalent cases feel consistent across hosts.
Alternatives considered:
- Keep host-owned unavailable messages and only align wording: rejected because ownership would still be split.
- Force all hosts to pre-normalize everything into “available only” and hide gaps: rejected because it would reduce diagnostic honesty.
Decision 5 — The existing Livewire settings table remains the settings-catalog subtype renderer
Decision: Keep SettingsCatalogSettingsTable as the renderer for the settings-catalog subtype inside the normalized settings family.
Rationale: The table already provides search, sort, pagination, query-string isolation by context, and a details action. Replacing it would add risk and produce little user benefit. The problem is not that the table exists; the problem is that the host, rather than the family, currently decides when the table belongs to the surface.
Alternatives considered:
- Replace the table with static Blade markup: rejected because it would lose established usability and re-implement behavior already present.
- Split settings-catalog into its own separate family: rejected because the operator still experiences it as a settings detail subtype, not a separate product surface.
Decision 6 — Testing should prove cross-host sameness and DB-only behavior, then add a small fork guard
Decision: Reuse and extend the current feature tests for widgets, onboarding, verification DB-only behavior, policy-version settings, and finding diffs, then add one parity test per family and one focused guard against re-forking.
Rationale: The repo already has strong tests around verification and normalized detail content. The missing coverage is family-level sameness across hosts and explicit protection against new host forks. A small guard gives lasting value without forcing a generic UI compliance framework.
Alternatives considered:
- Rely only on manual smoke checks: rejected because the spec explicitly wants drift prevention.
- Add a large screenshot or browser-regression suite: rejected because it would be expensive relative to the bounded scope and existing feature-level coverage.