Automated PR created by Codex via Gitea API. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #465
51 KiB
Feature Specification: Spec 394 - Provider Freshness & Permission Semantics v1
Feature Branch: 394-provider-freshness-permission-semantics
Created: 2026-06-21
Status: Draft / Ready for implementation preparation review
Type: Bugfix / correctness / trust boundary / productization
Priority: P1
Runtime posture: Clean canonical replacement over existing provider freshness, provider readiness, verification, and required-permission count behavior. No legacy compatibility shim, no parallel provider health truth, no new provider integration, and no UI expansion.
Input: User-provided full Spec 394 draft plus repo truth from provider connections, required permissions, verification, provider capability, environment dashboard, workspace overview, governance inbox, restore/review readiness, and related completed specs.
Dependencies And Historical Context
Spec 394 is a correctness follow-up over existing provider scope, capability, verification, guidance, and readiness work:
- Spec 281 - Provider Connection Scope, completed/historical provider target-scope foundation.
- Spec 283 - Provider Capability Registry, implemented provider capability vocabulary and evaluator context.
- Spec 294 - Provider Verification Runtime Semantics Stabilization, completed provider/verification runtime context.
- Spec 339 - Provider Connection Scope Hardening, completed provider authority-source guardrails.
- Spec 353 - Provider Connections Resolution Guidance v1, implemented guidance hierarchy over existing provider truth.
- Spec 381 - Provider Resource Identity and Binding Foundation v1, completed provider-resource binding context, not modified by this spec.
- Spec 385 - Evidence and review readiness integration, completed downstream readiness context.
- Spec 390 - Restore readiness resolution adapter, prepared/runtime context for restore readiness consumers.
- Spec 393 - Evidence anchor reconciliation, adjacent trust-boundary cleanup pattern.
Repo-truth observations that shape this spec:
ProviderConnectionstoresverification_status,last_health_check_at,consent_status,is_enabled, scope fields, and provider identity metadata.ManagedEnvironmentPermissionstores permission rows withmanaged_environment_id,workspace_id,permission_key,status,details, andlast_checked_at.ManagedEnvironmentPermissionServicecompares configured required permissions against stored or live evidence but currently keys granted rows by permission key for one environment and does not expose a canonical provider-connection or verification-batch result.ManagedEnvironmentRequiredPermissionsViewModelBuildercurrently derivespresent,missing_application,missing_delegated,error, and freshness from permission row timestamps. Its filters still include the legacypresentlabel.ProviderConnectionSurfaceSummarymapsProviderVerificationStatus::Healthydirectly toReady, independent from permission freshness and required permission coverage.ProviderCapabilityEvaluatorblocks missing/error/stale permission evidence but is not the one canonical readiness and count contract for all product surfaces.ProviderReadinessResolutionAdapteralready detects stale health checks and stale permission snapshots for guidance cards, but this behavior is not the single source used by all provider health, table, badge, count, and downstream readiness consumers.- Provider UI guidance from Spec 353 is intentionally a bounded guidance layer over existing truth. Spec 394 must replace inconsistent truth calculations, not add a second visible guidance layer.
Spec Candidate Check (mandatory - SPEC-GATE-001)
- Problem: Provider readiness is a trust boundary, but current provider surfaces can derive health, freshness, required permission counts, and readiness from different local sources.
- Today's failure: Required Permissions can show ambiguous counts such as
Present 0while granted permission rows exist, and Provider Connections can showHealthyorReadyfromverification_status=healthyeven when verification evidence or permission evidence is stale. - User-visible improvement: Operators see one truthful provider state across Provider Connections, Required Permissions, Environment Dashboard, Workspace Overview, Governance Inbox, and downstream readiness surfaces. Stale, failed, unknown, missing, wrong-scope, or blocked provider evidence never appears as
HealthyorReady. - Smallest enterprise-capable version: Consolidate provider readiness, verification freshness, permission coverage, row state, count semantics, recommended action, and capability-aware action visibility into one canonical resolver contract. Replace local visible health/readiness/count paths on affected existing surfaces. Add focused tests and one bounded browser smoke.
- Explicit non-goals: No new provider integration, no OAuth redesign, no new onboarding wizard, no new dashboard/card/page, no new raw evidence panel, no customer-facing provider internals, no broad Product Surface Contract Enforcement pass, no restore/review adapter rebuild beyond preventing direct provider surfaces from lying.
- Permanent complexity imported: One canonical resolver/result contract, a derived provider-readiness state family, explicit required-permission row/count vocabulary, focused Unit/Feature/Filament/Browser tests, and artifact/reporting obligations. No new table is expected by default.
- Why now: Provider readiness now feeds evidence capture, review readiness, restore readiness, governance checks, and customer-safe outputs. False readiness is a direct trust failure, not a cosmetic label issue.
- Why not local:
ProviderConnectionSurfaceSummary,ManagedEnvironmentRequiredPermissionsViewModelBuilder,ProviderCapabilityEvaluator,ProviderReadinessResolutionAdapter, dashboard builders, and tests already encode overlapping provider truth. Page-local fixes would preserve drift and allow stale verification to becomeHealthyelsewhere. - Approval class: Core Enterprise.
- Red flags triggered: New resolver abstraction, provider state vocabulary, multiple surfaces, and canonical semantics. Defense: the resolver replaces existing parallel truth for a security/trust boundary, has multiple real consumers now, remains derived unless existing schema cannot represent the contract, and explicitly forbids UI expansion and compatibility shims.
- Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | Gesamt: 11/12
- Decision: approve.
Candidate Source And Completed-Spec Guardrail
- Selected candidate: Provider Freshness & Permission Semantics v1.
- Source location: Direct user-provided Spec 394 draft in this conversation. Roadmap relationship is the manual-promotion lane
Provider readiness and onboarding productizationindocs/product/roadmap.mdanddocs/product/spec-candidates.md. - Why selected: The active auto-prep queue is empty, but the user explicitly provided a numbered manual candidate. Repo inspection confirms visible drift in provider readiness/count/freshness seams.
- Close alternatives deferred:
- Provider onboarding redesign: deferred because this spec must fix truth before adding setup flows.
- Secondary-action density cleanup from Spec 353: deferred because this spec is correctness, not action-density polish.
- Cross-domain indicator runtime follow-through: deferred because this spec is provider-specific readiness truth.
- Governance artifact lifecycle/retention runtime: unrelated trust lane.
- Product Surface Contract Enforcement pass: broader later pass, not needed to fix provider readiness truth.
- Completed-spec check:
- No
specs/394-*package existed before this preparation. - Specs 281, 283, 294, 339, 353, and 381 contain completed-task, implementation, review, close-out, or smoke-history signals and are read-only historical context.
- Spec 353 guidance surfaces and UI audit artifacts must not be rewritten into preparation state. Spec 394 may require follow-up updates only if implementation materially changes visible UI behavior.
- No
- Smallest viable implementation slice: Existing provider readiness/health/count consumers only: Provider Connections, Required Permissions, Environment Dashboard provider area, Workspace Overview provider signals, Governance Inbox provider-related items if present, and direct provider-blocking summaries used by restore/evidence/review readiness.
- Gate result: PASS. The candidate is user-provided, unprepared, not completed, roadmap-aligned, and narrowed to a bounded trust-boundary correction.
Spec Scope Fields (mandatory)
- Scope: workspace-owned provider connection plus managed-environment permission/readiness scope.
- Primary Routes / Surfaces:
/admin/provider-connections/admin/provider-connections/{record}/admin/provider-connections/{record}/edit/admin/workspaces/{workspace}/environments/{environment}/required-permissions/admin/workspaces/{workspace}/environments/{environment}/adminWorkspace Overview provider/readiness signals where repo-real- Governance Inbox provider-related rows where repo-real
- Restore, evidence, review, and report readiness summaries only where they directly consume provider health/readiness state
- Data Ownership:
ProviderConnectionremains workspace-owned and managed-environment-linked.ManagedEnvironmentPermissionremains managed-environment-owned permission evidence with workspace scope.- Provider verification remains represented by existing provider connection fields,
OperationRunverification reports, and permission row timestamps unless implementation proves a minimal clean schema change is necessary. - Provider account/context for v1 is the current
ProviderConnectionidentity: provider connection ID, workspace ID, managed environment ID, provider key, persisted provider identity metadata already stored on the connection, and verificationOperationRuncontext that references the same provider connection. A grant without an exact current provider connection, managed environment, workspace, and provider-key match cannot satisfy a required permission. - No new persisted truth is expected by default. Any schema change must be clean, pre-production, reversible where practical, and justified in updated spec/plan before implementation.
- RBAC:
- Workspace membership and managed-environment entitlement are required before any provider readiness result or route is exposed.
- Product-safe readiness summaries require view capability.
- Provider-changing actions such as verify, reconnect, refresh grants, repair permissions, or admin consent require existing provider management/run capabilities.
- Technical detail requires an existing technical capability if present; otherwise use the stricter provider management capability.
- Non-member or wrong workspace/environment remains deny-as-not-found. Member without capability remains 403 or disabled/hidden per existing UI enforcement.
For canonical-view or mixed-scope specs:
- Default filter behavior when environment-context is active: Provider readiness must be resolved for the explicit workspace/environment/provider connection context. Workspace-wide summaries may aggregate only actor-authorized environments and must not pick wrong-scope grants.
- Explicit entitlement checks preventing cross-tenant leakage: Resolver methods must scope by workspace, managed environment, provider connection, provider key, and actor entitlement before resolving grants, rows, links, or actions. Wrong-scope grants must not satisfy current required permissions.
- Provider account/context stop condition: If implementation discovers a required permission cannot be safely reconciled from the current
ProviderConnectionidentity, managed-environment scope, provider key, and verification context, stop and update spec/plan before adding a separate provider-account identifier or schema.
Canonical Provider Readiness Contract
The implementation must create or consolidate one resolver/service with behavior equivalent to:
ProviderReadinessResolver::forWorkspace($workspace, ?User $actor)
ProviderReadinessResolver::forEnvironment($environment, ?User $actor)
ProviderReadinessResolver::forProviderConnection($providerConnection, ?User $actor)
ProviderReadinessResolver::requiredPermissions($providerConnection, $scope, ?User $actor)
ProviderReadinessResolver::freshness($providerConnection, ?User $actor)
Exact class and method names may differ if repo ownership points to a better namespace. The product-facing decision must still be one canonical contract consumed by affected surfaces.
Resolver result fields:
provider_connection_id
scope_type
scope_id
readiness_state
connection_state
verification_state
verification_checked_at nullable
verification_expires_at nullable
is_verification_fresh
required_count
granted_required_count
missing_required_count
blocked_required_count
expired_required_count
unknown_required_count
not_applicable_count
permission_rows[]
primary_reason
blocking_reasons[]
recommended_action
can_view_technical_detail
can_manage_provider
child_results[] nullable for workspace/environment aggregate entry points
Entry-point result shape:
forProviderConnection(...),requiredPermissions(...), andfreshness(...)return one provider-scoped resolver result.forEnvironment(...)returns one aggregate result withscope_type=environment,provider_connection_id=nullwhen multiple provider connections are represented, andchild_results[]containing provider-scoped resolver results for actor-authorized provider connections in that environment.forWorkspace(...)returns one aggregate result withscope_type=workspace,provider_connection_id=null, andchild_results[]containing environment/provider-scoped results for actor-authorized environments and provider connections in that workspace.- Aggregate readiness uses the same state precedence as provider-scoped readiness, sums canonical count fields from child results, and takes the recommended action from the highest-severity child blocker. Product surfaces must not hand-roll workspace or environment aggregation from raw permission rows.
Each permission row fields:
permission_key
product_label
provider_permission_name nullable
state
required_for
is_required
is_effective
matched_grant_id nullable
last_verified_at nullable
reason
recommended_action nullable
is_technical_only
Canonical Product States
Provider-facing product states:
ReadyNeeds attentionBlockedNot configuredExpiredFailedUnknown
Provider readiness mapping:
- Provider connected + verification fresh + all required permissions effective ->
Ready - Provider connected + permissions partially missing ->
Needs attention - Provider connected + required permissions blocked or admin consent denied ->
Blocked - Provider missing or disconnected ->
Not configured - Verification stale ->
Expired - Verification failed ->
Failed - Insufficient data ->
Unknown
Individual required permission row states:
GrantedMissingBlockedExpiredUnknownNot applicable
Row mapping:
- Fresh matching grant exists ->
Granted - No matching grant ->
Missing - Provider denies or admin consent blocked ->
Blocked - Matching grant exists but verification is stale ->
Expired - Insufficient verification data ->
Unknown - Permission not required in this scope ->
Not applicable
Required permission counts:
required_count
granted_required_count
missing_required_count
blocked_required_count
expired_required_count
unknown_required_count
not_applicable_count
Invariant:
required_count =
granted_required_count
+ missing_required_count
+ blocked_required_count
+ expired_required_count
+ unknown_required_count
not_applicable_count is outside required_count unless a later spec explicitly changes that product contract.
Forbidden ambiguous product-facing count labels:
PresentPresent 0OK countPermission countGranted rowsRaw grants
These terms may remain only in internal technical notes when clearly defined and not shown as default product UI.
Functional Requirements
- FR-394-001: Any visible provider health/readiness state must be derived from the canonical resolver. Legacy helpers must delegate to it or be removed.
- FR-394-002: Stale provider verification must never render as
Healthy,Ready,Current, orOK. - FR-394-003: Connected/configured provider state must not be treated as provider readiness.
- FR-394-004: Required permission summary counts and row states must come from the same resolver result.
- FR-394-005: A grant is effective only when it matches the current workspace, managed environment, provider connection, provider account/context represented by the current provider connection identity, provider namespace, required permission, and fresh verification basis.
- FR-394-006: Permission evidence from stale verification must not satisfy current required permissions. It may appear only as technical/historical detail when authorized.
- FR-394-007: Unknown permission state fails closed as
Unknown,Needs attention, or a non-ready equivalent. - FR-394-008: Missing permissions must produce actionable product copy and a truthful next action such as review required permissions, verify provider, reconnect provider, request admin consent, or open provider connection.
- FR-394-009: Provider readiness consumers in provider connections, required permissions, environment/workspace readiness, governance inbox, and direct downstream readiness summaries must use the canonical resolver or be documented as an explicit remaining local path with reason and follow-up.
- FR-394-010: Default product UI must not expose raw provider payloads, raw permission JSON, opaque provider IDs, grant object IDs, token details, verification payloads, Graph/API dumps, or internal job/run IDs.
- FR-394-011: Default permission labels must explain product purpose first. Raw provider permission names may appear only as secondary technical detail where authorized.
- FR-394-012: Resolver output must be deterministic. Multiple matching grants must use explicit ordering: correct scope, fresh verification batch, non-revoked grant, most recent verification timestamp, deterministic ID tie-breaker.
- FR-394-013: Provider-changing actions must require existing management/run capability. View-only users may view product-safe summaries when authorized but cannot execute provider-changing actions.
- FR-394-014: Downstream readiness surfaces that depend on provider access must not override provider blockers from stale, failed, unknown, or missing provider state.
- FR-394-015: Old tests, fixtures, labels, translation keys, query ordering, action keys, and fallback logic preserving misleading provider health or
Present 0behavior must be removed or updated.
UX Requirements
Provider Connection summary should show:
- Provider
- Connection state
- Verification state
- Last verified at
- Required permissions state
- At most one primary action
Required Permissions should show canonical counts such as:
Required permissions: 8
Granted: 6
Missing: 2
Expired: 0
Rows should show:
- Permission purpose
- State
- Required for
- Last verified
- Next action
Stale provider copy:
Provider verification expired.
Verify this provider to refresh permission status.
Required permissions cannot be trusted until verification is current.
Missing permission copy:
Required permission missing.
Admin consent is required.
Provider access needs attention.
Allowed primary actions by state:
Ready-> View providerNeeds attention-> Review required permissionsExpired-> Verify providerFailed-> Review provider errorNot configured-> Connect providerBlocked-> Resolve provider blockerUnknown-> Check provider status
This spec must reduce or preserve visible complexity. Wrong labels/states are replaced, not duplicated.
UI Surface Impact (mandatory - UI-COV-001)
Does this spec add, remove, rename, or materially change any reachable UI surface?
- No UI surface impact
- Existing page changed
- New page/route added
- Navigation changed
- Filament panel/provider surface changed
- New modal/drawer/wizard/action added
- New table/form/state added
- Customer-facing surface changed
- Dangerous action changed
- Status/evidence/review presentation changed
- Workspace/environment context presentation changed
UI/Productization Coverage
- Route/page/surface:
- Provider Connections list/view/edit
- Environment Required Permissions
- Environment Dashboard provider area
- Workspace Overview provider/readiness signals where repo-real
- Governance Inbox provider-related items where repo-real
- Direct restore/evidence/review readiness summaries where provider state is consumed
- Current or new page archetype:
- Provider Connections: existing Provider / Integration Strategic Surface from
ui-009-provider-connections.md - Required Permissions: existing Provider / Integration Domain Pattern Surface from
ui-077-required-permissions.md - Environment Dashboard and Workspace Overview: existing operator overview surfaces
- Governance Inbox: existing operator decision queue
- Provider Connections: existing Provider / Integration Strategic Surface from
- Design depth: Domain Pattern Surface / Strategic Surface follow-through over existing surfaces.
- Repo-truth level: repo-verified.
- Existing pattern reused: Spec 353 provider readiness guidance card, existing Filament resource/page surfaces, existing
BadgeCatalog/BadgeRenderer, existingUiEnforcement/WorkspaceUiEnforcement, existing OperationRun start UX for verification. - New pattern required: one canonical provider readiness resolver/result contract; no new dashboard, no new onboarding wizard, no new raw technical table.
- Screenshot required: yes for focused browser smoke only if visible labels/counts/actions change, likely under
specs/394-provider-freshness-permission-semantics/artifacts/screenshots/. - Page audit required: update existing page reports only if visible page behavior materially changes:
docs/ui-ux-enterprise-audit/page-reports/ui-009-provider-connections.mddocs/ui-ux-enterprise-audit/page-reports/ui-077-required-permissions.md- dashboard/workspace/governance page reports only if implementation materially changes default-visible provider/readiness behavior there
- Customer-safe review required: no direct customer-facing provider detail is added; downstream customer-safe readiness must not expose raw provider data.
- Dangerous-action review required: yes for provider-changing actions already present. They must remain capability-gated and confirmation/audit-safe where high-impact.
- Coverage files updated or explicitly not needed:
docs/ui-ux-enterprise-audit/route-inventory.mddocs/ui-ux-enterprise-audit/design-coverage-matrix.mddocs/ui-ux-enterprise-audit/page-reports/...docs/ui-ux-enterprise-audit/strategic-surfaces.mddocs/ui-ux-enterprise-audit/grouped-follow-up-candidates.mddocs/ui-ux-enterprise-audit/unresolved-pages.mdN/A - no reachable UI surface impact
- No-impact rationale when applicable: N/A. Existing surfaces are materially changed because labels, states, counts, and primary actions may change.
Cross-Cutting / Shared Pattern Reuse
- Cross-cutting feature?: yes.
- Interaction class(es): status messaging, action links, dashboard signals, readiness summaries, provider guidance, permission rows/counts, support/technical disclosure, OperationRun verification links.
- Systems touched:
App\Support\Providers\TargetScope\ProviderConnectionSurfaceSummaryApp\Support\ResolutionGuidance\Adapters\ProviderReadinessResolutionAdapterApp\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilderApp\Services\Intune\ManagedEnvironmentPermissionServiceApp\Support\Providers\Capabilities\ProviderCapabilityEvaluatorApp\Filament\Resources\ProviderConnectionResourceApp\Filament\Pages\EnvironmentRequiredPermissionsApp\Support\EnvironmentDashboard\EnvironmentDashboardSummaryBuilderApp\Support\Workspaces\WorkspaceOverviewBuilderApp\Support\GovernanceInbox\GovernanceInboxSectionBuilder- existing restore/evidence/review readiness adapters where provider state is consumed
- Existing pattern(s) to extend: Spec 353 readiness guidance hierarchy, existing capability evaluator, existing provider connection scope hardening rules, existing OperationRun verification start path, existing badge catalog.
- Shared contract / presenter / builder / renderer to reuse: Existing
BadgeCatalog/BadgeRenderer,ProviderOperationStartResultPresenter,OperationRunLinks,RequiredPermissionsLinks,UiEnforcement/WorkspaceUiEnforcement, and provider capability registry/evaluator where they remain the correct input. - Why the existing shared path is sufficient or insufficient: Existing paths each solve part of the problem. None currently owns the complete product truth for readiness, freshness, permission row states, count invariants, scope matching, and action capability together.
- Allowed deviation and why: one canonical resolver is allowed because current local truth is already duplicated across multiple real product surfaces and can produce false
Healthy/Ready. - Consistency impact: Provider Connections, Required Permissions, dashboard guidance, workspace summaries, governance inbox, and direct downstream readiness summaries must share state names, freshness behavior, count semantics, next-action labels, and raw-detail gating.
- Review focus: no stale verification as healthy/ready, no
Present 0, no wrong-scope grant satisfaction, no raw provider payloads, no compatibility shim, no second readiness truth.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, existing provider verification start/proof links only.
- Shared OperationRun UX contract/layer reused: existing
StartVerification,ProviderOperationStartResultPresenter,OperationUxPresenter,OperationRunLinks, andOperationRunService. - Delegated start/completion UX behaviors: verify-provider action must keep existing queued/deduped/blocked/run-link behavior. This spec may change when the action is primary or visible, not how OperationRun UX is composed.
- Local surface-owned behavior that remains: resolver output decides recommended action and capability visibility; surfaces render it through existing action patterns.
- Queued DB-notification policy: unchanged. No new queued notification family.
- Terminal notification path: unchanged central lifecycle mechanism.
- Exception required?: none.
Provider Boundary / Platform Core Check
- Shared provider/platform boundary touched?: yes.
- Boundary classification: mixed. Provider-owned evidence and permission names feed a platform-core readiness contract.
- Seams affected: provider connection state, verification freshness, required permission coverage, permission evidence, provider capability evaluation, provider health labels, dashboard readiness signals, workspace/governance summaries, and downstream readiness blockers.
- Neutral platform terms preserved or introduced: provider connection, verification, freshness, required permission, granted permission, effective permission, permission coverage, readiness, scope, recommended action.
- Provider-specific semantics retained and why: Microsoft Graph permission names and admin-consent details remain necessary as secondary technical/operator detail for the current Microsoft provider.
- Why this does not deepen provider coupling accidentally: product-facing labels use provider-neutral and purpose-first language. Raw Microsoft permission names stay secondary and do not define the platform-core readiness vocabulary.
- Follow-up path: deeper provider onboarding and permission resolution adapter remains a later follow-up; this spec fixes current truth only.
UI / Surface Guardrail Impact
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| Provider Connections list/view/edit | yes | Native Filament resource plus shared provider summary/guidance | provider readiness, health, actions, verification proof | table, detail, header/action state | no | Existing routes only |
| Environment Required Permissions | yes | Native Filament page plus Blade summary/matrix | permission rows/counts, freshness, provider action | page summary, filters, rows, copy | no | Existing route only |
| Environment Dashboard provider area | yes | Existing dashboard builder/view | readiness signal and next action | dashboard decision/guidance | no | Existing dashboard only |
| Workspace Overview provider/readiness signal | conditional yes | Existing builder/view | workspace readiness aggregation | overview signal | no | Only if repo-real provider signals are consumed |
| Governance Inbox provider-related items | conditional yes | Existing inbox builder/view | provider blocker item truth | queue item/status/action | no | Only if repo-real provider items are consumed |
| Restore/evidence/review readiness summaries | conditional yes | Existing resources/builders | provider blocker propagation | readiness state | no | Direct provider-state consumers only |
Decision-First Surface Role
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Provider Connections view | Primary Decision Surface | Decide whether this provider can be trusted now | readiness state, verification freshness, permission coverage, one action | capability rows, verification history, technical provider detail | Primary because connection readiness is a trust authority | provider administration | removes parallel health/count interpretation |
| Provider Connections list | Secondary Context Surface | Find which connection needs attention | readiness state and scope-safe summary | detail page | Secondary because detail owns the decision | workspace integration scanning | avoids multiple top-level truth labels |
| Environment Required Permissions | Primary Decision Surface | Decide which permission/freshness blocker must be resolved | canonical counts, row states, freshness, one action | raw provider permission names and technical details | Primary for permission remediation | permission remediation workflow | replaces Present ambiguity |
| Environment Dashboard provider area | Secondary Context Surface | Confirm provider blocker and jump to resolver-owned remediation | canonical blocker and next action | provider/permission detail page | Secondary because dashboard summarizes | environment operations | prevents dashboard from claiming ready from old evidence |
| Workspace Overview / Governance Inbox | Secondary Context Surface | Prioritize affected environments/items | canonical blocker state and link | environment/provider details | Secondary aggregation | portfolio triage | avoids contradictory readiness signals |
Audience-Aware Disclosure
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Provider Connections | operator-MSP, workspace owner, support when authorized | readiness, verification freshness, required permission state, next action | last verification, capability groups, permission coverage | raw provider IDs/payloads excluded by default | View provider, verify provider, review permissions, connect provider | technical details capability-gated | canonical resolver result owns state once |
| Required Permissions | operator-MSP, workspace owner, support when authorized | required/granted/missing/blocked/expired/unknown counts and rows | provider permission names as secondary detail | raw permission JSON excluded by default | verify provider or review consent | raw details collapsed/gated | summary count aggregates rows |
| Dashboard/Workspace/Inbox | operator-MSP, readonly where authorized | blocker state and target link | none or concise proof | raw provider detail never default | open provider/permissions/remediation | technical detail hidden | aggregations consume resolver output |
UI/UX Surface Classification
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Provider Connections list | List / Integration | CRUD / List-first Resource | Open provider or verify/review blocker | row opens detail | required | More/header | unchanged existing grouping | /admin/provider-connections |
/admin/provider-connections/{record} |
workspace, environment, provider | Provider connection | readiness and freshness | none |
| Provider Connections view/edit | Detail / Configuration Authority | Provider readiness detail/config | verify provider, review permissions, reconnect, or view provider | dedicated detail/edit | N/A | header More / details | existing confirmations retained | /admin/provider-connections |
existing view/edit routes | workspace, environment, provider | Provider connection | canonical readiness | none |
| Required Permissions | List / Guidance / Diagnostic | read-first remediation page | verify provider or review/admin consent | same page matrix | forbidden | page body secondary links | none added | required permissions route | same page | workspace and environment | Required permissions | canonical counts and row states | existing inline diagnostic page |
| Environment Dashboard | Overview / Decision | operator environment dashboard | open provider remediation | cards/links | N/A | dashboard guidance | unchanged | environment route | same | workspace/environment/provider | Provider readiness | provider blocker cannot be overridden | none |
| Workspace Overview / Governance Inbox | Queue / Overview | aggregation/triage | open environment/provider remediation | item/action link | N/A | item secondary links | unchanged | existing routes | existing target routes | workspace and environment | Provider readiness | blocker state | conditional only |
Operator Surface Contract
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Provider Connections | Workspace operator | Decide whether provider is ready now | integration list/detail | Can TenantPilot rely on this provider right now? | connection state, verification freshness, permission coverage, recommended action | raw provider permission names, verification history | connection, verification, permission coverage, readiness | TenantPilot provider metadata or provider verification operation | Verify provider, Review required permissions, Connect provider, View provider | existing credential/disable/reconnect actions only |
| Required Permissions | Workspace operator | Decide which permission or freshness issue blocks provider use | diagnostic remediation page | Are required permissions effective for this scope? | canonical counts, row states, last verified, next action | provider permission names, technical detail | permission row state, freshness, readiness | verification operation only | Verify provider, Request admin consent, Open connection | none added |
| Dashboard/Workspace/Inbox | Governance operator | Prioritize provider blockers across environments | overview/queue | Which provider blocker needs attention? | canonical state, impact, link | deeper provider detail | readiness only | none | Open provider/permissions | none added |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no persisted source of truth by default. One derived canonical resolver becomes the product-facing decision contract.
- New persisted entity/table/artifact?: no by default. Existing
ProviderConnection,ManagedEnvironmentPermission,OperationRun, and verification reports should be used first. - New abstraction?: yes, a canonical provider readiness resolver/result contract.
- New enum/state/reason family?: yes, derived product-facing readiness and permission row states. They must change behavior and next action, not just presentation.
- New cross-domain UI framework/taxonomy?: no.
- Current operator problem: Operators can be told a provider is healthy/ready or permission coverage is absent/present based on local, stale, or ambiguous calculations.
- Existing structure is insufficient because: Existing structures separately compute health, guidance, capability, required-permission counts, and freshness. At least
ProviderConnectionSurfaceSummary,ManagedEnvironmentRequiredPermissionsViewModelBuilder,ProviderCapabilityEvaluator, andProviderReadinessResolutionAdaptercan diverge. - Narrowest correct implementation: one derived resolver over existing records and verification evidence, adopted by affected provider/readiness consumers, replacing visible labels/counts instead of adding new UI.
- Ownership cost: one canonical contract, focused tests, migration of existing consumers, and future review discipline that provider readiness changes go through the resolver.
- Alternative intentionally rejected: local copy/count fixes in Required Permissions and Provider Connections. That would leave stale health/readiness drift elsewhere.
- Release truth: current-release trust-boundary correction.
Compatibility posture
TenantPilot is pre-production. Do not preserve old Healthy, Ready, Present, fallback, compatibility alias, translation key, fixture, or test behavior when it conflicts with this spec. Canonical replacement wins.
Testing / Lane / Runtime Impact
- Test purpose / classification: Unit for resolver state/count logic, Feature for DB/scope/RBAC/action semantics, Filament/Livewire for provider pages/actions, Browser for focused end-to-end UI proof.
- Validation lane(s): fast-feedback, confidence, browser. PostgreSQL only if implementation adds schema or relies on PostgreSQL-specific query/index behavior.
- Why this classification and these lanes are sufficient: The core risk is deterministic business truth and visible trust-boundary rendering. Unit/Feature tests prove semantics; Filament tests prove actions and visibility; one browser smoke proves the real product surfaces no longer display forbidden labels/states.
- New or expanded test families: focused
Spec394provider readiness resolver tests, provider connection/required-permission feature tests, capability-boundary tests, and one browser smoke. - Fixture / helper cost impact: moderate. Tests need workspace, managed environment, provider connection, permission evidence, verification timestamps, and actor capabilities. Helpers must stay explicit and not widen default provider setup globally.
- Heavy-family visibility / justification: one bounded browser smoke only. No broad heavy-governance family is justified.
- Special surface test profile: provider/integration strategic surface, diagnostic matrix page, dashboard/overview readiness signal.
- Standard-native relief or required special coverage: standard Filament coverage plus one browser smoke for visible state/count/action behavior.
- Reviewer handoff: verify no stale provider renders as healthy/ready, counts equal row aggregation, wrong-scope/stale grants fail closed, readonly users cannot run provider actions, raw provider payloads are absent by default, and no compatibility shim remains.
- Budget / baseline / trend impact: contained feature-local increase. Escalate if implementation creates broad browser/heavy-governance suites or shared expensive setup defaults.
- Escalation needed: document-in-feature if a narrow local path remains with reason; follow-up-spec if downstream adapters require a broader readiness propagation contract.
- Active feature PR close-out entry: Provider Freshness / Permission Semantics Guardrail.
- Planned validation commands:
cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec394cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections tests/Feature/RequiredPermissions tests/Feature/Verificationcd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec394ProviderFreshnessPermissionSmokeTest.phpcd apps/platform && ./vendor/bin/sail bin pint --dirty --format agentgit diff --check
User Scenarios & Testing
User Story 1 - Stale verification is not healthy (Priority: P1)
As a workspace operator, I need stale provider verification to be visibly non-ready so I do not rely on provider data that TenantPilot has not recently verified.
Why this priority: This prevents the most dangerous false-green provider state.
Independent Test: Create a provider connection with verification_status=healthy, old last_health_check_at, and old permission evidence. The resolver and UI return Expired or Needs attention, never Healthy or Ready, and the primary action is to verify provider.
Acceptance Scenarios:
- Given a successful verification older than the freshness window, When provider readiness is rendered, Then the provider state is
ExpiredorNeeds attention, notHealthyorReady. - Given stale permission grants, When required permission rows are resolved, Then row states are
Expiredand coverage does not count them as granted.
User Story 2 - Required permission counts match effective rows (Priority: P1)
As an operator reviewing permissions, I need the summary counts to match the visible required permission rows so remediation is not misleading.
Why this priority: Ambiguous Present counts break trust and can send users to the wrong action.
Independent Test: Seed required permission rows with fresh effective grants, missing rows, blocked rows, expired rows, and unknown rows. The summary counts equal row-state aggregation and no product UI shows Present 0.
Acceptance Scenarios:
- Given six required rows in
Grantedand two inMissing, When the Required Permissions page renders, Thenrequired_count=8,granted_required_count=6,missing_required_count=2, and the row count matches. - Given granted raw rows that are wrong-scope, When the resolver runs for the current provider connection, Then those rows do not count as granted.
User Story 3 - Wrong-scope and unknown grants fail closed (Priority: P1)
As a security-conscious operator, I need TenantPilot to reject wrong-scope, unknown, or out-of-date permission evidence instead of assuming access is available.
Why this priority: Scope leakage or stale evidence can produce false confidence across workspaces, environments, provider connections, or provider accounts.
Independent Test: Create grants for another workspace, another environment, another provider connection, and a stale verification batch. Current-scope coverage remains Missing, Expired, or Unknown.
Acceptance Scenarios:
- Given a grant belongs to another workspace or environment, When current provider readiness is resolved, Then the grant is ignored and readiness is not
Ready. - Given insufficient verification data, When readiness is rendered, Then the state is
UnknownorNeeds attentionand no provider-changing action appears for readonly users.
User Story 4 - Product surfaces share one provider truth (Priority: P2)
As an operator moving between dashboard, provider connection, required permissions, and governance work surfaces, I need the provider blocker to be consistent and actionable.
Why this priority: It prevents contradictory signals and reduces search work after the core resolver is correct.
Independent Test: Run focused feature and browser tests across Provider Connections, Required Permissions, Environment Dashboard, Workspace Overview, and Governance Inbox provider-related items. Each uses the same resolver state and recommended action.
Acceptance Scenarios:
- Given a provider is stale, When dashboard and provider details render, Then both point to verification and neither shows ready/healthy.
- Given missing required permissions, When dashboard guidance opens Required Permissions, Then the target page shows the same missing-permission blocker and canonical counts.
Non-Functional Requirements
- NFR-394-001: Resolver decisions must be DB-only during render and must not call Microsoft Graph or any external provider.
- NFR-394-002: Queries must be scope-safe and deterministic; no implicit database ordering.
- NFR-394-003: Default UI must remain calm, decision-first, and no more complex than current surfaces.
- NFR-394-004: Raw provider payloads, tokens, credentials, API response bodies, and grant IDs must not appear in default product UI or audit metadata.
- NFR-394-005: Filament v5 / Livewire v4.0+ compliance is required. Current repo uses Livewire 4.1.4.
- NFR-394-006: Provider panel registration remains unchanged in
apps/platform/bootstrap/providers.php.
Data And Truth-Source Requirements
Prefer existing schema and relations:
provider_connections.verification_statusprovider_connections.last_health_check_atprovider_connections.consent_statusprovider_connections.is_enabledprovider_connections.providerprovider_connections.workspace_idprovider_connections.managed_environment_id- existing provider identity metadata fields/casts on
provider_connections managed_environment_permissions.workspace_idmanaged_environment_permissions.managed_environment_idmanaged_environment_permissions.permission_keymanaged_environment_permissions.statusmanaged_environment_permissions.detailsmanaged_environment_permissions.last_checked_at- provider verification
OperationRuncontext/report where repo-real
Potential clean concepts only if existing data cannot represent the contract:
provider_verification_checked_atprovider_verification_expires_atprovider_verification_statepermission_grants.verification_batch_idpermission_grants.scope_typepermission_grants.scope_idrequired_permissions.provider_keyrequired_permissions.product_purpose
If implementation proves one of these is needed, stop and update spec/plan before adding migrations.
Provider account/context is not an implicit free-form match. For v1, it is derived from the current ProviderConnection identity and same-provider verification context. If existing records cannot distinguish two provider accounts behind the same workspace/environment/provider key, affected permissions must resolve as Unknown or the implementation must stop and update spec/plan before adding schema.
Acceptance Criteria
- AC-394-001: Stale provider is not
HealthyorReady; primary action is verify/refresh provider. - AC-394-002: Fresh provider with all effective required permissions is
Ready. - AC-394-003: Required permission counts match row states and no UI shows
Present 0while granted rows are visible. - AC-394-004: Missing permission blocks readiness and recommends permission remediation.
- AC-394-005: Wrong-scope grants do not satisfy current required permissions.
- AC-394-006: Stale grants produce
Expiredpermission row state and non-ready provider readiness. - AC-394-007: Unknown state fails closed and never renders as ready/healthy.
- AC-394-008: Readonly users cannot trigger verify/reconnect/manage provider actions and cannot view raw provider technical detail.
- AC-394-009: Affected pages show one provider readiness/health truth by default.
- AC-394-010: Affected pages do not gain new cards, sections, evidence/proof links, or long technical tables as part of this spec.
Success Criteria
- A stale provider never appears healthy on Provider Connections, Required Permissions, Environment Dashboard, or provider readiness consumers.
- Required permission summary counts equal canonical row-state aggregation.
- Connected provider state and provider readiness are visibly distinct.
- Wrong-scope and stale grants are excluded from effective permission coverage.
- Provider-changing actions are capability-gated.
- No raw provider payload or technical permission dump appears by default.
- No legacy compatibility shim preserves old provider health or
Presentsemantics.
Regression Risks
- Existing tests may expect old
Healthybehavior. Mitigation: update tests to canonical behavior without weakening the resolver. - Fixture inconsistencies may appear when counts change. Mitigation: fix fixtures to represent canonical grants and scope.
- Downstream surfaces may lose
Readystates. Mitigation: if provider state is stale or incomplete, losingReadyis correct. - Readonly users may lose technical detail. Mitigation: product-safe summary remains visible where authorized; technical detail remains manage/technical-capability gated.
- Provider labels may become too technical. Mitigation: product labels first, raw provider names secondary/internal only.
Assumptions
- TenantPilot remains pre-production for this feature area; no legacy customer data compatibility is required.
- Existing
ProviderConnection,ManagedEnvironmentPermission, and verification report/OperationRun data can represent the v1 contract unless implementation proves otherwise. - Microsoft remains the first provider, but product-facing readiness vocabulary must stay provider-neutral.
- No new dashboard, onboarding wizard, provider integration, or customer-facing provider detail is required.
Open Questions
- None blocking preparation. During implementation, if current schema cannot distinguish fresh verification batch scope from stale permission rows, update spec/plan before adding schema.
Follow-Up Spec Candidates
- Provider Onboarding & Permissions Resolution Adapter: guided setup/remediation flow after canonical readiness semantics are stable.
- Product Surface Contract Enforcement provider pass: broader cross-surface enforcement if additional downstream consumers keep local provider truth.
- Provider secondary-action density cleanup: optional Spec 353 follow-up if the canonical state change reveals action clutter.
Required Implementation Report
Later implementation must report:
- Files changed.
- Resolver/API created or consolidated.
- Old local provider health/readiness logic removed or replaced.
- Required permission count logic source.
- Tests added/updated.
- Browser flows run.
- Evidence that stale verification no longer renders
HealthyorReady. - Evidence that required permission counts match rows.
- Evidence that wrong-scope grants are excluded.
- Confirmation that no legacy compatibility shim was added.
- Confirmation that visible UI complexity did not increase.
- Remaining known unrelated failures, if any.