---

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.

- [X] T001 Create ActionSurface namespaces in app/Support/Ui/ActionSurface/
- [X] T002 [P] Add guard test skeleton in tests/Feature/Guards/ActionSurfaceContractTest.php
- [X] 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.

- [X] T004 Create enums for component/profile/slot in app/Support/Ui/ActionSurface/Enums/ActionSurfaceComponentType.php
- [X] T005 [P] Create slot + exemption value objects in app/Support/Ui/ActionSurface/ActionSurfaceExemption.php
- [X] T006 [P] Create declaration + defaults DTOs in app/Support/Ui/ActionSurface/ActionSurfaceDeclaration.php
- [X] T007 Implement profile definitions (required slots per profile) in app/Support/Ui/ActionSurface/ActionSurfaceProfileDefinition.php
- [X] T008 Implement in-scope discovery (tenant discovery roots + admin explicit registrations/routes; exclude Widgets and System panel) in app/Support/Ui/ActionSurface/ActionSurfaceDiscovery.php
- [X] T009 Implement declaration contract validation (declare-or-exempt; reason required; More label; Export default) in app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
- [X] 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.

- [X] T011 [US1] Implement the CI guard that runs validation in tests/Feature/Guards/ActionSurfaceContractTest.php
- [X] T012 [US1] Add baseline exemptions registry in app/Support/Ui/ActionSurface/ActionSurfaceExemptions.php (reason required, explicit class allowlist with shrink-over-time rule)
- [X] T013 [US1] Wire exemptions into validator output in app/Support/Ui/ActionSurface/ActionSurfaceValidator.php
- [X] T014 [US1] Make guard output actionable (class + slot + hint) in tests/Feature/Guards/ActionSurfaceContractTest.php
- [X] T015 [US1] Add tests proving widgets are excluded from scope in tests/Feature/Guards/ActionSurfaceContractTest.php
- [X] 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.

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

- [X] T024 [P] [US3] Add non-member 404 route test on representative operations detail route in tests/Feature/Rbac/ActionSurfaceRbacSemanticsTest.php
- [X] 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
- [X] 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
- [X] T027 [US3] Ensure disabled-UI semantics are covered for the same action (visible + disabled + standard tooltip) in tests/Feature/Filament/EntraGroupSyncRunResourceTest.php
- [X] 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

- [X] T028 [P] Run formatter on changed files via vendor/bin/sail bin pint --dirty
- [X] T029 Run focused guard tests via vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php
- [X] 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 4–5 can proceed in parallel) → Polish (Phase 6)

## Parallel Opportunities

- Phase 2: DTOs/enums (T004–T006) can be done in parallel.
- US2: Profile definition + validator rules (T016–T017) 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).
