TenantAtlas/specs/082-action-surface-contract/tasks.md
ahmido a770b32e87 feat: action-surface contract inspect affordance + clickable rows (#100)
Implements Spec 082 updates to the Filament Action Surface Contract:

- New required list/table slot: InspectAffordance (clickable row via recordUrl preferred; also supports View action or primary link column)
- Retrofit view-only tables to remove lone View row action buttons and use clickable rows
- Update validator + guard tests, add golden regression assertions
- Add docs: docs/ui/action-surface-contract.md

Tests (local via Sail):
- vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php
- vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceValidatorTest.php
- vendor/bin/sail artisan test --compact tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php
- vendor/bin/sail artisan test --compact tests/Feature/Filament/EntraGroupSyncRunResourceTest.php

Notes:
- Filament v5 / Livewire v4 compatible.
- No destructive-action behavior changed in this PR.

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #100
2026-02-08 20:31:36 +00:00

8.4 KiB
Raw Blame History

description
Task list for Spec 082 implementation

Tasks: Action Surface Contract + CI Enforcement

Input: Design documents from /specs/082-action-surface-contract/
Prerequisites: plan.md (required), spec.md (required), research.md, data-model.md, contracts/, quickstart.md
Tests: Required (Pest) — this feature adds/changes CI enforcement.

Phase 1: Setup (Shared Infrastructure)

Purpose: Introduce the new support namespace and a guard-test entry point.

  • T001 Create ActionSurface namespaces in app/Support/Ui/ActionSurface/
  • T002 [P] Add guard test skeleton in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T003 [P] Add validator test skeleton in tests/Feature/Guards/ActionSurfaceValidatorTest.php

Phase 2: Foundational (Blocking Prerequisites)

Purpose: Core contract model + discovery + validation that all user stories rely on.

  • T004 Create enums for component/profile/slot in app/Support/Ui/ActionSurface/Enums/ActionSurfaceComponentType.php
  • T005 [P] Create slot + exemption value objects in app/Support/Ui/ActionSurface/ActionSurfaceExemption.php
  • T006 [P] Create declaration + defaults DTOs in app/Support/Ui/ActionSurface/ActionSurfaceDeclaration.php
  • T007 Implement profile definitions (required slots per profile) in app/Support/Ui/ActionSurface/ActionSurfaceProfileDefinition.php
  • T008 Implement in-scope discovery (tenant discovery roots + admin explicit registrations/routes; exclude Widgets and System panel) in app/Support/Ui/ActionSurface/ActionSurfaceDiscovery.php
  • T009 Implement declaration contract validation (declare-or-exempt; reason required; More label; Export default) in app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T010 Add fast unit-style tests for validator rules in tests/Feature/Guards/ActionSurfaceValidatorTest.php (pure validation logic, no DB or Filament boot)

Checkpoint: Validator can enumerate + validate in-scope components deterministically.


Phase 3: User Story 1 — Prevent incomplete UI action surfaces (Priority: P1) 🎯 MVP

Goal: CI fails if an in-scope Filament component lacks a declaration (or an explicit exemption with a non-empty reason).

Independent Test: Add a new in-scope Filament component without a declaration; run the guard and confirm it fails with an actionable message; add a declaration/exemption and confirm it passes.

  • T011 [US1] Implement the CI guard that runs validation in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T012 [US1] Add baseline exemptions registry in app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php (reason required, explicit class allowlist with shrink-over-time rule)
  • T013 [US1] Wire exemptions into validator output in app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T014 [US1] Make guard output actionable (class + slot + hint) in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T015 [US1] Add tests proving widgets are excluded from scope in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T031 [US1] Add tests proving unknown classes are not auto-exempted and every exemption reason is non-empty in tests/Feature/Guards/ActionSurfaceContractTest.php

Checkpoint: Guard passes on main branch state, but blocks missing declarations going forward.


Phase 4: User Story 2 — Consistent, enterprise-grade actions and empty-state guidance (Priority: P2)

Goal: Provide consistent action-surface conventions (More grouping, Export default for RunLog/ReadOnly, empty-state CTA) and demonstrate them on representative surfaces.

Independent Test: Pick one CRUD-style list and one run-log style list; verify each has expected action areas (header/row/bulk/empty-state; detail header actions) and consistent ordering/grouping.

  • T016 [P] [US2] Define required slots for CRUD/ReadOnly/RunLog/RelationManager profiles in app/Support/Ui/ActionSurface/ActionSurfaceProfileDefinition.php
  • T017 [P] [US2] Enforce defaults: More label + Export expectation for ReadOnly/RunLog in app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
  • T018 [US2] Add a declaration to a representative CRUD surface in app/Filament/Resources/PolicyResource.php
  • T019 [US2] Ensure list empty-state CTA exists for the CRUD surface in app/Filament/Resources/PolicyResource/Pages/ListPolicies.php
  • T020 [US2] Add a declaration to a representative RunLog surface in app/Filament/Resources/OperationRunResource.php
  • T021 [US2] Ensure Export bulk action is present (or exempted with reason) for the RunLog surface in app/Filament/Resources/OperationRunResource.php
  • T022 [US2] Add a declaration to one embedded relationship sub-list in app/Filament/Resources/PolicyResource/RelationManagers/VersionsRelationManager.php
  • T023 [US2] Add tests asserting the representative declarations satisfy required slots in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T032 [US2] Add representative runtime test asserting PolicyResource row/bulk grouping uses “More” conventions in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T033 [US2] Add representative runtime test asserting canonical tenantless “View run” link usage in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T035 [US2] Add golden regression tests for “view-only lists use clickable rows without row actions” in tests/Feature/Guards/ActionSurfaceContractTest.php
  • T036 [US2] Document action-surface contract rules (including “no lone View button; prefer clickable rows”) in docs/ui/action-surface-contract.md

Checkpoint: At least one CRUD + one RunLog + one embedded sub-list visibly follow the conventions.


Phase 5: User Story 3 — Predictable RBAC behavior for members vs non-members (Priority: P3)

Goal: Validate consistent 404 vs 403 semantics and disabled-UI behavior for capability-gated actions.

Independent Test: Use a representative surface and verify (a) non-member receives not-found, and (b) member without capability receives forbidden and sees disabled UI with a helpful explanation.

  • T024 [P] [US3] Add non-member 404 route test on representative operations detail route in tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php
  • T025 [US3] Add member-without-capability 403 server-side test by attempting to execute ListEntraGroupSyncRuns::sync_groups as a readonly member in tests/Feature/Filament/EntraGroupSyncRunResourceTest.php
  • T026 [US3] In that 403 test, assert no EntraGroupSyncJob is pushed and no EntraGroupSyncRun is created for the tenant in tests/Feature/Filament/EntraGroupSyncRunResourceTest.php
  • T027 [US3] Ensure disabled-UI semantics are covered for the same action (visible + disabled + standard tooltip) in tests/Feature/Filament/EntraGroupSyncRunResourceTest.php
  • T034 [US3] Add representative observability/audit regression assertion for an operation-start action (OperationRun record present with scope + actor) in tests/Feature/Guards/ActionSurfaceContractTest.php

Checkpoint: One surface per profile has coverage for 404 vs 403 semantics.


Phase 6: Polish & Cross-Cutting Concerns

  • T028 [P] Run formatter on changed files via vendor/bin/sail bin pint --dirty
  • T029 Run focused guard tests via vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php
  • T030 Run RBAC semantics test via vendor/bin/sail artisan test --compact tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php

Dependencies & Execution Order

  • Setup (Phase 1) → Foundational (Phase 2) → US1 (Phase 3) → US2/US3 (Phases 45 can proceed in parallel) → Polish (Phase 6)

Parallel Opportunities

  • Phase 2: DTOs/enums (T004T006) can be done in parallel.
  • US2: Profile definition + validator rules (T016T017) can be done in parallel.
  • US3: Test scaffolding (T024) can be done in parallel with US2 retrofit tasks.

Parallel Example: US2

  • T018 (PolicyResource declaration) can be implemented in parallel with T020 (OperationRunResource declaration).

Implementation Strategy

MVP First (US1 only)

  1. Complete Phase 1 + Phase 2.
  2. Implement Phase 3 (US1) guard + exemptions.
  3. Validate guard behavior by adding/removing a declaration locally.

Incremental Delivery

  • Add US2 representative surfaces next (PolicyResource + OperationRunResource + one RelationManager).
  • Add US3 RBAC semantics tests last (keeps scope tight while contract infrastructure stabilizes).