TenantAtlas/specs/082-action-surface-contract/plan.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

4.6 KiB
Raw Permalink Blame History

Implementation Plan: Action Surface Contract + CI Enforcement

Branch: 082-action-surface-contract | Date: 2026-02-08 | Spec: specs/082-action-surface-contract/spec.md Input: Feature specification from specs/082-action-surface-contract/spec.md

Summary

Introduce a declarative “Action Surface Declaration” for every in-scope admin UI component (Resources, Pages, embedded relationship sub-lists), enforce it via a deterministic Pest guard in CI, and add representative runtime tests for constitution-critical action behavior.

Key behavior:

  • Contract profiles define minimum required action slots (list header/row/bulk/empty-state, detail header).
  • Declarations must satisfy each required slot or explicitly exempt it with a reason.
  • CI fails on missing declarations, missing required slots, or empty exemption reasons.
  • Representative runtime tests verify grouping/confirmation/RBAC/canonical-run-link behavior on selected surfaces.

Technical Context

Language/Version: PHP 8.4.x
Primary Dependencies: Laravel 12, Filament v5, Livewire v4
Storage: PostgreSQL (Sail)
Testing: Pest v4 (PHPUnit 12 runner)
Target Platform: Web application (Laravel Sail for local; Dokploy for deploy)
Project Type: Laravel monolith (admin console via Filament panels)
Performance Goals: Contract validation completes in < 1s locally/CI (pure PHP, no network)
Constraints:

  • Deterministic CI enforcement (no Livewire browser interactions)
  • No new external calls introduced
  • Must preserve RBAC semantics (non-member 404; member missing capability 403)
  • Must not change panel architecture (tenant/admin/system panels remain)
  • No deep runtime introspection of every Filament action in CI for this iteration Scale/Scope: ~100 Filament classes (Resources/Pages/RelationManagers); enforcement is repo-wide within scope

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Inventory-first: N/A (this feature is UI governance; no inventory model changes)
  • Read/write separation: N/A (no new domain writes introduced by the validator)
  • Graph contract path: PASS (no new Graph calls)
  • Deterministic capabilities: PASS (capability rules stay registry-driven)
  • RBAC-UX: PASS (enforcement continues to use central UI helpers; server-side remains authoritative)
  • Run observability: PASS (validator runs in CI only; no operations started)
  • Data minimization: PASS (no new storage)
  • Badge semantics (BADGE-001): N/A
  • Filament UI Action Surface Contract: PASS (this feature implements the CI gate itself)

Plan Phases

Phase 0 — Research (output: research.md)

Decide and document:

  • How to enumerate in-scope classes for tenant + admin panels (excluding widgets)
  • How declarations are attached (static method vs attributes vs config)
  • What “slots” exist and how exemptions are represented (reason required; tracking optional)
  • How the Pest guard reports actionable failures

Phase 1 — Design (outputs: data-model.md, contracts/*, quickstart.md)

Design artifacts:

  • Data model for declarations, slots, exemptions, and profiles
  • JSON schema contract for the declaration payload (for future tooling)
  • Quickstart explaining how to add a declaration + how to run the guard

Phase 2 — Planning (output: tasks.md later via /speckit.tasks)

Implementation plan will include:

  • New support classes under app/Support/Ui/ActionSurface/**
  • Pest guard test under tests/Feature/Guards/**
  • Minimal retrofit for existing “bulk none” surfaces via declarations + targeted exemptions (repo-green first)
  • Representative runtime assertions for action grouping, confirmation, and canonical run links

Project Structure

Documentation (this feature)

specs/082-action-surface-contract/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   ├── Resources/
│   ├── Pages/
│   └── System/           # out-of-scope for this features validator
├── Providers/Filament/   # panel providers (tenant/admin/system)
└── Support/
    ├── Rbac/             # UiEnforcement + WorkspaceUiEnforcement (existing)
    └── Ui/ActionSurface/ # NEW: profiles, slots, declarations, validator

tests/
└── Feature/
    └── Guards/           # NEW: Action surface contract CI gate

Structure Decision: Laravel monolith. Action-surface enforcement ships as support-domain classes + a Pest guard.

Complexity Tracking

No constitution violations required.