TenantAtlas/specs/139-verify-access-permissions-assist/data-model.md
ahmido b182f55562 feat: add verify access required permissions assist (#168)
## Summary
- add an in-place Required Permissions assist to the onboarding Verify Access step via a Filament slideover
- route permission-related verification remediation links into the assist first and keep deep-dive links opening in a new tab
- add view-model and link-behavior helpers plus focused feature, browser, RBAC, and unit coverage for the new assist

## Scope
- onboarding wizard Verify Access UX
- Required Permissions assist rendering and link behavior
- Spec 139 artifacts, contracts, and checklist updates

## Notes
- branch: `139-verify-access-permissions-assist`
- commit: `b4193f1`
- worktree was clean at PR creation time

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #168
2026-03-14 02:00:28 +00:00

5.1 KiB

Data Model — Spec 139 (Verify Access Required Permissions Assist)

Existing persisted entities reused

TenantOnboardingSession (existing)

  • Source: app/Models/TenantOnboardingSession.php
  • Role in this feature:
    • Anchors the current onboarding draft and current wizard step.
    • Holds the selected provider connection and latest verification run reference in state.
  • Relevant persisted state:
    • tenant_id
    • current_step
    • state.provider_connection_id
    • state.verification_operation_run_id

OperationRun (existing)

  • Source: app/Models/OperationRun.php
  • Role in this feature:
    • Supplies the latest stored verification result used by Verify Access.
    • Remains the source of truth for the existing verification report.
  • Relevant persisted context:
    • context.provider_connection_id
    • context.target_scope
    • context.verification_report

TenantPermission dataset (existing)

  • Source: tenant_permissions via TenantPermissionService::compare(... persist: false, liveCheck: false)
  • Role in this feature:
    • Supplies the current DB-only permission diagnostics summary and missing-permission breakdown used by the assist and full page.

Computed view models

VerificationAssistVisibility (computed)

  • Purpose: determines whether the Verify Access step should expose View required permissions.
  • Inputs:
    • Stored verification report overall/check state.
    • Existing permission diagnostics summary.
    • Stale verification context for the selected provider connection.
  • Shape:
    • is_visible: bool
    • reason: 'permission_blocked' | 'permission_attention' | 'hidden_ready' | 'hidden_irrelevant'

VerificationAssistViewModel (computed)

  • Purpose: compact payload rendered inside the slideover.
  • Derived from:
    • verificationReportViewData() output
    • TenantRequiredPermissionsViewModelBuilder::build($tenant, ...)
  • Shape:
    • tenant: { id: int, external_id: string, name: string }
    • verification: { overall: string|null, status: string|null, is_stale: bool, stale_reason: string|null }
    • overview: { overall: string, counts: { missing_application: int, missing_delegated: int, present: int, error: int }, freshness: { last_refreshed_at: string|null, is_stale: bool } }
    • missing_permissions: { application: PermissionRow[], delegated: PermissionRow[] }
    • copy: { application: string, delegated: string }
    • actions: AssistActions
    • fallback: { has_incomplete_detail: bool, message: string|null }

PermissionRow (existing computed shape reused)

  • Source: TenantRequiredPermissionsViewModelBuilder
  • Shape:
    • key: string
    • type: 'application' | 'delegated'
    • description: string|null
    • features: string[]
    • status: 'granted' | 'missing' | 'error'
    • details: array|null

AssistActions (computed)

  • Purpose: explicit, authorization-safe actions shown in the slideover.
  • Shape:
    • full_page: { label: string, url: string, opens_in_new_tab: true, is_secondary: true }
    • copy_application: { label: string, payload: string, available: bool }
    • copy_delegated: { label: string, payload: string, available: bool }
    • grant_admin_consent: { label: string, url: string|null, opens_in_new_tab: bool, available: bool }
    • manage_provider_connection: { label: string, url: string|null, opens_in_new_tab: bool, available: bool }
    • rerun_verification: { label: string, handled_by_existing_wizard: true }

VerificationLinkBehavior (computed)

  • Purpose: normalize how Verify Access next-step links are rendered.
  • Shape:
    • label: string
    • url: string
    • kind: 'external' | 'internal-diagnostic' | 'internal-inline-safe'
    • opens_in_new_tab: bool
    • show_new_tab_hint: bool

State transitions

Assist visibility transition

  • Hidden → Visible when:
    • verification report indicates permission-related blockers or relevant needs-attention state, and
    • the current user remains authorized for the underlying tenant context.
  • Visible → Hidden when:
    • verification becomes fully ready with no relevant permission guidance, or
    • authorization context no longer permits the assist.

Wizard continuity invariant

  • Opening the assist does not change TenantOnboardingSession.current_step.
  • Closing the assist does not mutate onboarding draft state.
  • Opening the full page from the assist does not navigate the current onboarding tab away from the wizard.

Copy-action availability invariant

  • A copy action is available only when the corresponding copy.* payload is a non-empty string.
  • Empty payloads result in omitted or replaced controls, not broken actions.

Authorization model reuse

  • Onboarding wizard access continues to depend on workspace membership plus onboarding capability rules.
  • Required Permissions deep-dive access continues to depend on tenant entitlement and existing page authorization.
  • The assist is visible only when both contexts are valid enough to avoid leaking tenant or permission detail.

No persistence changes

  • No new tables.
  • No new route-backed models.
  • No new onboarding-only permissions store.
  • No mutation to the existing Required Permissions page role.