TenantAtlas/docs/ui/action-surface-contract.md
ahmido be314c577f Spec 400: rebuild Tenantial homepage visuals (#387)
## Summary
- rebuild the public Tenantial homepage around an evidence-first Microsoft tenant governance narrative
- replace the old hero visual with a new static dashboard preview and add dedicated Trust Bar and Feature Pillars sections
- update the shared public shell, navigation, footer, dark design tokens, assets, and homepage content to match the new brand direction
- align website smoke coverage and Spec 400 artifacts with the rebuilt homepage

## Testing
- not run in this pass
- updated website smoke specs under apps/website/tests/smoke

## Note
- `website-dev` was pushed to `origin` so the requested PR base exists remotely
- the remote `website-dev` branch is an ancestor of `origin/dev`, so this PR may also show upstream `dev` history relative to that base

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #387
2026-05-18 14:38:11 +00:00

4.1 KiB

Action surface contract

Status: Active
Last reviewed: 2026-04-30
Use for: Action placement and affordance rules for Filament resources, pages, and relation managers
Do not use for: Skipping authorization, confirmation, or resource-specific UX review

This project enforces a small “action surface contract” for Filament Resources / Pages / RelationManagers to keep table UIs consistent, quiet, and safe.

Inspect affordance (required)

Any list-style surface that exposes records must provide an inspect affordance so an admin can open a record.

Surface-type decision tree

The inspect model is driven by the declaration surfaceType:

  • CRUD / List-first Resource Use one-click open by default, normally recordUrl(). PrimaryLinkColumn is allowed only as an explicit exception with a concrete reason.
  • Read-only Registry / Report Use one-click open by default, normally recordUrl(). This includes scan-first reporting surfaces such as Monitoring Operations, Review Register, Evidence Overview, and read-only registry resources.
  • Queue / Review Use explicit inspect (Inspect row action or equivalent same-page selected detail). Do not make the full row clickable.
  • History / Audit Use explicit inspect (Inspect row action or equivalent same-page selected detail). Do not make the full row clickable.
  • Config-lite Edit-as-inspect is allowed, but it still uses one obvious open path and must not add a competing View action.

Accepted implementations

  • Clickable rows (preferred): set recordUrl() for the table.
  • Inspect action: a row action used only on queue / review or history / audit surfaces where context must stay on the same page.
  • Primary link column: a column that is clearly the primary affordance to open the record, with an explicit PrimaryLinkColumn reason in the declaration.

Rule: no lone “View” button

Avoid rendering a table that only has a single inspect-style row action on a clickable-row surface. This creates visual noise and adds an unnecessary Actions column.

Preferred approach:

  • Make the row clickable via recordUrl() and set actions([]) so no Actions column is rendered.

PrimaryLinkColumn exception rule

Use PrimaryLinkColumn only when full-row click is the wrong interaction model for that specific surface.

  • The declaration must use a clickable surface type (CrudListFirstResource, ReadOnlyRegistryReport, or ConfigLite).
  • The declaration must include a non-empty primaryLinkColumnReason.
  • Queue / review and history / audit surfaces may not use PrimaryLinkColumn as a shortcut around explicit inspect.

Reporting / evidence register rule

Review and evidence registers are governed as ReadOnlyRegistryReport surfaces.

  • ReviewRegister and EvidenceOverview keep clickable-row inspection as the primary open path.
  • Do not add a duplicate View review or equivalent open action beside the row click.
  • Safe non-inspect shortcuts may remain when they are clearly secondary.

More-menu ordering

Governed ActionGroup and BulkActionGroup menus use one stable order:

  • Navigation or inspect helpers first
  • Non-destructive workflow or lifecycle actions next
  • Destructive actions last

Examples:

  • Policies: export before sync, sync before ignore/delete
  • Backup schedules: run/retry before archive or force delete
  • Tenants: related onboarding and safe navigation shortcuts before sync or verification, with archive/force delete trailing

Placeholder groups are forbidden

ActionGroup and BulkActionGroup exist to hold real secondary actions, not to reserve layout space.

  • Do not render an empty More menu after visibility, record-state, or RBAC filtering removes every effective action.
  • On clickable-row surfaces with only one safe shortcut, that shortcut may still live under More when it preserves a cleaner scan-first list.

RBAC / safety

  • If the current user cannot inspect a record, recordUrl() must return null for that record.
  • UI visibility is not authorization; always enforce permissions at the policy / resource level.