5.3 KiB
Phase 0 Research: Action Surface Contract v1.1
Decision: Add a first-class ActionSurfaceType enum to ActionSurfaceDeclaration while keeping ActionSurfaceProfile
Rationale: ActionSurfaceProfile currently governs which slots are required, but it does not distinguish constitution-level interaction semantics. The repo needs to tell the difference between clickable-row CRUD or registry surfaces and legitimate explicit-inspect queue or audit surfaces. A first-class surfaceType field makes that distinction explicit without forcing slot requirements and behavioral rules into the same enum.
Alternatives considered:
- Replace
ActionSurfaceProfileentirely: rejected because slot requirements and constitution surface semantics are different concerns and existing declarations already rely on the profile model. - Derive surface type from metadata or inferred heuristics: rejected because the clarified spec requires a first-class declaration-level field and because inference would keep validator failures ambiguous.
Decision: Keep inspect-model compatibility rules close to the existing contract stack
Rationale: The narrowest implementation is one new enum plus validator logic and small helper methods where needed. That keeps the feature inside the current ActionSurfaceDeclaration / ActionSurfaceValidator architecture and avoids introducing a second action-governance registry or policy layer.
Alternatives considered:
- Create a new
ActionSurfaceTypeDefinitionregistry or service: rejected because the slice does not justify another framework layer. - Enforce the new rules in tests only: rejected because the main validator must become the primary contract gate, not just the rendered tests.
Decision: Extend primary discovery to declared system-panel table pages only
Rationale: The six enrolled system list pages already have declarations and targeted tests, but the main discovery pass still excludes them. The safest extension is to scan app/Filament/System/Pages/** narrowly for declared, table-backed pages so the main validator covers them without accidentally enrolling auth, dashboard, widget, or other deferred system surfaces.
Alternatives considered:
- Hardcode an allowlist of six system classes: rejected because it would preserve a parallel discovery model and create more manual maintenance.
- Broadly discover every page under
app/Filament/System/Pages: rejected because it would sweep in deferred surfaces such as auth, runbooks, and break-glass tooling.
Decision: Keep current panel-scope metadata unchanged for this slice
Rationale: The feature needs system-panel discovery coverage, not a new panel taxonomy. The current codebase does not have an active consumer that requires a System panel scope enum, so adding one now would widen the slice without solving the immediate operator problem.
Alternatives considered:
- Add
ActionSurfacePanelScope::System: rejected because no current validation or runtime rule depends on it, and the spec does not require it. - Infer system scope through panel providers and extend all scope tests: rejected as unnecessary expansion beyond the current feature goal.
Decision: Split enforcement between fast validator tests and representative Livewire render tests
Rationale: Validator tests are the right seam for declaration-time rules such as required surfaceType, allowed affordance combinations, and required exception reasons. Livewire render tests are the right seam for business-visible behavior such as row click actually existing, explicit inspect actually preserving context, and More groups actually rendering helpers first, workflow actions next, and destructive actions last.
Alternatives considered:
- Declaration-only guard coverage: rejected because the constitution explicitly rejects declaration-only conformance when rendered behavior drifts.
- Browser-only coverage: rejected because it would be slower, broader, and less precise than the current Livewire table guard pattern already used in the repo.
Decision: Treat PrimaryLinkColumn as an exception path that requires an explicit reason
Rationale: The spec needs stronger control over linked-column inspect affordances, but the repo does not need a dedicated exception object or secondary taxonomy for that. Requiring an explicit reason on the declaration is enough to keep the exception visible and reviewable.
Alternatives considered:
- Allow
PrimaryLinkColumnanywhere the enum is present: rejected because the constitution requires a concrete reason when row click is not the correct primary inspect model. - Add a new exception class hierarchy: rejected because it would add structure without a separate current-release problem to solve.
Decision: Keep the two reference docs in lockstep with validator behavior
Rationale: The repo already has two developer-facing references for this domain: docs/ui/action-surface-contract.md and docs/product/standards/filament-actions-ux.md. The feature should update both together so implementation guidance, spec language, and guard behavior stay aligned.
Alternatives considered:
- Update only the constitution: rejected because day-to-day implementation guidance lives in the shorter reference docs.
- Update only one doc and let the other lag: rejected because that would recreate the ambiguity the feature is meant to remove.