TenantAtlas/specs/122-empty-state-consistency/contracts/empty-states.openapi.yaml
ahmido 73a3a62451 Spec 122: Empty state consistency pass (#148)
## Summary
- unify empty-state UX across the six in-scope Filament list pages
- move empty-state ownership toward resource `table()` definitions while preserving existing RBAC behavior
- add focused Pest coverage for empty-state rendering, CTA outcomes, populated-state regression behavior, and action-surface compliance
- add the Spec 122 planning artifacts and product discovery documents used for this pass

## Changed surfaces
- `PolicyResource`
- `BackupSetResource`
- `RestoreRunResource`
- `BackupScheduleResource`
- `WorkspaceResource`
- `AlertDeliveryResource`

## Tests
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/EmptyStateConsistencyTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/Alerts/AlertDeliveryViewerTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/CreateCtaPlacementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/PolicySyncStartSurfaceTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/BackupScheduling/BackupScheduleLifecycleAuthorizationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/BackupSetUiEnforcementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/RestoreRunUiEnforcementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Notes
- Filament v5 / Livewire v4.0+ compliance is preserved.
- Panel provider registration remains unchanged in `bootstrap/providers.php`.
- No new globally searchable resources were added.
- Destructive actions were not introduced by this pass.
- Alert Deliveries is documented as the explicit no-header-action exemption for the empty-state CTA relocation rule.
- Manual light/dark visual QA evidence is still expected in the PR/review artifact set for the remaining checklist items (`T018`, `T025`).

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #148
2026-03-08 02:17:51 +00:00

287 lines
8.5 KiB
YAML

openapi: 3.1.0
info:
title: TenantPilot Internal Empty State Contracts
version: 1.0.0
description: |
Internal review contract for Spec 122.
These are Filament list surfaces, not public API endpoints. The document exists so the
feature has an explicit, reviewable contract under specs/.../contracts/.
paths:
/admin/t/{tenant}/policies:
get:
summary: Tenant policies list empty state
description: Renders the policies list. When no rows exist, the page must expose the EmptyStateContract for the policies surface.
parameters:
- $ref: '#/components/parameters/TenantPathParam'
responses:
'200':
description: Policies list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/PolicyEmptyStateSurface'
/admin/t/{tenant}/backup-sets:
get:
summary: Tenant backup sets list empty state
parameters:
- $ref: '#/components/parameters/TenantPathParam'
responses:
'200':
description: Backup sets list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/BackupSetEmptyStateSurface'
/admin/t/{tenant}/restore-runs:
get:
summary: Tenant restore runs list empty state
parameters:
- $ref: '#/components/parameters/TenantPathParam'
responses:
'200':
description: Restore runs list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/RestoreRunEmptyStateSurface'
/admin/t/{tenant}/backup-schedules:
get:
summary: Tenant backup schedules list empty state
parameters:
- $ref: '#/components/parameters/TenantPathParam'
responses:
'200':
description: Backup schedules list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/BackupScheduleEmptyStateSurface'
/admin/workspaces:
get:
summary: Workspace management list empty state
responses:
'200':
description: Workspaces list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/WorkspaceEmptyStateSurface'
/admin/alert-deliveries:
get:
summary: Alert deliveries list empty state
responses:
'200':
description: Alert deliveries list rendered
content:
application/json:
schema:
$ref: '#/components/schemas/AlertDeliveryEmptyStateSurface'
components:
parameters:
TenantPathParam:
name: tenant
in: path
required: true
schema:
type: string
description: Current tenant route identifier for tenant-scoped Filament resources.
schemas:
EmptyStateContract:
type: object
additionalProperties: false
required:
- surface
- ownership_scope
- heading
- description
- icon
- primary_cta
- cta_count
properties:
surface:
type: string
ownership_scope:
type: string
enum: [tenant, workspace, workspace_context_monitoring]
heading:
type: string
description:
type: string
icon:
type: string
description: Heroicon identifier.
cta_count:
type: integer
const: 1
primary_cta:
$ref: '#/components/schemas/PrimaryCtaContract'
definition_source:
type: string
enum: [resource_table, page_helper_fallback]
preserved_capability_behavior:
type: string
enum: [disabled_with_explanation, hidden, mixed_by_existing_resource_rules]
PrimaryCtaContract:
type: object
additionalProperties: false
required:
- label
- intent
- target_surface
properties:
label:
type: string
intent:
type: string
enum: [create, navigate, queue_operation]
target_surface:
type: string
capability_aware:
type: boolean
notes:
type: string
nullable: true
PolicyEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: policy_list
ownership_scope:
const: tenant
heading:
const: No policies synced yet
description:
const: Sync your first tenant to see Intune policies here.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: Sync from Intune
intent:
const: queue_operation
BackupSetEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: backup_set_list
ownership_scope:
const: tenant
heading:
const: No backup sets
description:
const: Create a backup set to start protecting your configurations.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: Create backup set
intent:
const: create
RestoreRunEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: restore_run_list
ownership_scope:
const: tenant
heading:
const: No restore runs
description:
const: Start a restoration from a backup set.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: New restore run
intent:
const: create
BackupScheduleEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: backup_schedule_list
ownership_scope:
const: tenant
heading:
const: No schedules configured
description:
const: Set up automated backups.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: New backup schedule
intent:
const: create
WorkspaceEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: workspace_list
ownership_scope:
const: workspace
heading:
const: No workspaces
description:
const: Create your first workspace.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: New workspace
intent:
const: create
AlertDeliveryEmptyStateSurface:
allOf:
- $ref: '#/components/schemas/EmptyStateContract'
- type: object
properties:
surface:
const: alert_delivery_list
ownership_scope:
const: workspace_context_monitoring
heading:
const: No alert deliveries
description:
const: Deliveries appear automatically when alert rules fire.
primary_cta:
allOf:
- $ref: '#/components/schemas/PrimaryCtaContract'
- type: object
properties:
label:
const: View alert rules
intent:
const: navigate