212 lines
10 KiB
Markdown
212 lines
10 KiB
Markdown
# Data Model: Hard Filament Nativity Cleanup
|
|
|
|
## Overview
|
|
|
|
This feature introduces no new persisted entity, table, enum, or product-domain source of truth. It refactors three existing UI surfaces by replacing pseudo-native interaction contracts with native page-owned or component-owned state.
|
|
|
|
The data model for planning is therefore a set of derived UI-state and row-projection models that answer four questions:
|
|
|
|
1. What state is authoritative for each cleaned surface?
|
|
2. Which source truths continue to produce the rows and summaries?
|
|
3. Which values may be seeded from deeplinks, and which values must remain route- or entitlement-authoritative?
|
|
4. Which invariants must remain true after the cleanup?
|
|
|
|
## Existing Source Truths Reused Without Change
|
|
|
|
The following truths remain authoritative and are not redefined by this feature:
|
|
|
|
- `InventoryItem`, `InventoryLink`, `DependencyQueryService`, and `DependencyTargetResolver` for dependency edges and rendered targets
|
|
- the current tenant-context inventory route and inventory-record scope rules
|
|
- `TenantRequiredPermissionsViewModelBuilder`, `TenantPermission`, permission configuration, and provider guidance links for required-permissions truth
|
|
- the route-scoped tenant on `/admin/tenants/{tenant:external_id}/required-permissions`
|
|
- `EvidenceSnapshot`, `TenantReview`, `ArtifactTruthPresenter`, and the current workspace-context entitlement rules for evidence overview rows
|
|
- existing capability registries, `WorkspaceContext`, tenant membership checks, and current deny-as-not-found boundaries
|
|
|
|
This feature changes how these truths are controlled and rendered, not what they mean.
|
|
|
|
## New Derived Planning Models
|
|
|
|
### DependencyEdgesTableState
|
|
|
|
**Type**: embedded detail-surface state
|
|
**Source**: Livewire component state on inventory item detail
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `inventoryItemId` | int | Required current detail record key |
|
|
| `tenantId` | int | Required tenant-context key derived from the current panel or record scope |
|
|
| `direction` | string | Allowed values: `all`, `inbound`, `outbound`; default `all` |
|
|
| `relationshipType` | string or null | Null means all relationship types; otherwise one allowed relationship type key |
|
|
|
|
**Validation rules**
|
|
|
|
- `inventoryItemId` must resolve to the current authorized record.
|
|
- `tenantId` must match the current tenant-context scope.
|
|
- `direction` must stay inside the three allowed values.
|
|
- `relationshipType` must be null or a recognized relationship type value.
|
|
|
|
### DependencyEdgeRow
|
|
|
|
**Type**: derived row projection
|
|
**Source**: `DependencyQueryService` plus `DependencyTargetResolver`
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `relationshipType` | string | Canonical relationship family for grouping or filter matching |
|
|
| `targetType` | string | Current target kind, including `missing` when unresolved |
|
|
| `targetId` | string or null | External or internal target identifier |
|
|
| `renderedTarget` | array | Existing rendered badge and link payload |
|
|
| `isMissing` | boolean | Derived from `targetType === missing` |
|
|
| `missingTitle` | string | Existing descriptive fallback text for unresolved targets |
|
|
|
|
**Invariants**
|
|
|
|
- Row membership must stay tenant-isolated.
|
|
- Missing-target rendering must preserve current operator hints.
|
|
- Render-time behavior must remain DB-only with no Graph access.
|
|
|
|
### RequiredPermissionsTableState
|
|
|
|
**Type**: page-owned derived table state
|
|
**Source**: native Filament table filters and search on `TenantRequiredPermissions`
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `routeTenantExternalId` | string | Authoritative tenant scope from the route |
|
|
| `status` | string | Allowed values: `missing`, `present`, `error`, `all` |
|
|
| `type` | string | Allowed values: `all`, `application`, `delegated` |
|
|
| `features` | list<string> | Zero or more selected feature keys |
|
|
| `search` | string | Native table search text |
|
|
| `seededFromQuery` | boolean | True only during initial mount when deeplink values were present |
|
|
|
|
**Validation rules**
|
|
|
|
- The route tenant always wins over tenant-like query values.
|
|
- Query values may seed `status`, `type`, `features`, and `search` only at initial mount.
|
|
- `features` must be a normalized unique list of known feature keys.
|
|
|
|
### RequiredPermissionsSummaryProjection
|
|
|
|
**Type**: derived page summary model
|
|
**Source**: `TenantRequiredPermissionsViewModelBuilder` evaluated against the currently active normalized filter state
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `counts` | object | Existing counts for missing application, missing delegated, present, and error rows |
|
|
| `overall` | string or null | Existing overall readiness state |
|
|
| `freshness` | object | Existing freshness payload including stale or not stale |
|
|
| `featureImpacts` | list<object> | Existing per-feature impact summary |
|
|
| `copyPayloads` | object | Existing application and delegated copy payloads |
|
|
| `issues` | list<object> | Existing derived guidance and next-step content |
|
|
|
|
**Invariants**
|
|
|
|
- Summary and table rows must be derived from the same active filter state.
|
|
- Copy payload semantics must remain consistent with current expectations.
|
|
- Tenant scope must not be mutable through filter state.
|
|
|
|
### PermissionReviewRow
|
|
|
|
**Type**: derived table row
|
|
**Source**: `TenantRequiredPermissionsViewModelBuilder`
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `permissionKey` | string | Stable permission identifier |
|
|
| `type` | string | `application` or `delegated` |
|
|
| `status` | string | Current permission review status |
|
|
| `description` | string | Human-readable permission description |
|
|
| `features` | list<string> | Feature tags associated with the permission |
|
|
| `details` | object | Existing supporting metadata used for inline review only |
|
|
|
|
### EvidenceOverviewTableState
|
|
|
|
**Type**: workspace-context table state
|
|
**Source**: native Filament table search and optional query-seeded entitled tenant prefilter
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `workspaceId` | int | Required current workspace context |
|
|
| `authorizedTenantIds` | list<int> | Entitled tenant ids available to the actor |
|
|
| `tenantFilter` | int or null | Current entitled tenant prefilter, nullable when not active |
|
|
| `search` | string | Native table search across tenant-facing row labels |
|
|
| `seededFromQuery` | boolean | True only when the initial request carried a prefilter |
|
|
|
|
**Validation rules**
|
|
|
|
- `tenantFilter` must be null or one of the actor's entitled tenant ids.
|
|
- Missing workspace membership continues to produce `404`.
|
|
- Non-entitled tenant ids must not leak through filter state, row counts, or drilldowns.
|
|
|
|
### EvidenceOverviewRow
|
|
|
|
**Type**: derived workspace report row
|
|
**Source**: current snapshot query plus `ArtifactTruthPresenter`
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `tenantId` | int | Entitled tenant identifier |
|
|
| `tenantName` | string | Current display label |
|
|
| `snapshotId` | int | Current active snapshot id for drilldown |
|
|
| `artifactTruth` | object | Existing truth badge and explanation payload |
|
|
| `freshness` | object | Existing freshness badge payload |
|
|
| `generatedAt` | string or null | Timestamp label |
|
|
| `missingDimensions` | int | Existing burden metric |
|
|
| `staleDimensions` | int | Existing burden metric |
|
|
| `nextStep` | string | Existing next-step text |
|
|
| `viewUrl` | string | Current tenant evidence drilldown URL |
|
|
|
|
**Invariants**
|
|
|
|
- Row drilldowns must stay workspace-safe and tenant-entitlement-safe.
|
|
- Derived-state memoization must remain effective.
|
|
- Render-time behavior must remain DB-only.
|
|
|
|
### CleanupAdmissionCandidate
|
|
|
|
**Type**: planning-only admission check
|
|
**Source**: implementation audit only when a possible extra hit is discovered
|
|
|
|
| Field | Type | Notes |
|
|
|------|------|-------|
|
|
| `surfaceKey` | string | Stable human-readable identifier |
|
|
| `path` | string | File or route path for the potential extra surface |
|
|
| `matchesProblemClass` | boolean | Must be true to qualify |
|
|
| `opensArchitectureQuestion` | boolean | Must be false to qualify |
|
|
| `decision` | string | `include` or `defer` |
|
|
| `reason` | string | Explicit justification for the decision |
|
|
|
|
## State Transition Rules
|
|
|
|
### Rule 1 - Deeplink seed to native active state
|
|
|
|
- Initial request query values may seed filter state on `TenantRequiredPermissions` and `EvidenceOverview`.
|
|
- After initial mount, active state belongs to the native page table or component, not to `request()`.
|
|
|
|
### Rule 2 - Route scope remains authoritative
|
|
|
|
- `TenantRequiredPermissions` may never replace its route tenant from query values.
|
|
- Inventory dependency state may never replace the current detail record or tenant context.
|
|
- Evidence overview may never reveal non-entitled tenant rows through a prefilter.
|
|
|
|
### Rule 3 - No new persistence or mirrored helper truth
|
|
|
|
- Filter state stays session-backed or Livewire-backed only where Filament already provides that behavior.
|
|
- No new database table, JSON helper artifact, or persisted UI-state mirror is introduced.
|
|
|
|
## Safety Rules
|
|
|
|
- No cleaned surface may introduce a second wrapper contract that simply restyles the current non-native behavior.
|
|
- No cleaned surface may widen current workspace or tenant scope behavior.
|
|
- No cleaned surface may lose current empty-state meaning, next-step clarity, or inspect destination correctness.
|
|
- No page or component may call Graph or other remote APIs during render as part of this cleanup.
|
|
|
|
## Planned Test Mapping
|
|
|
|
| Model / Rule | Existing Coverage | Planned Additions |
|
|
|---|---|---|
|
|
| `DependencyEdgesTableState` | `tests/Feature/InventoryItemDependenciesTest.php`, dependency tenant-isolation and query-service tests | native component test for direction and relationship interaction |
|
|
| `RequiredPermissionsTableState` | `tests/Feature/Rbac/TenantRequiredPermissionsTrustedStateTest.php`, unit filter normalization tests | page-level native table test |
|
|
| `RequiredPermissionsSummaryProjection` | current unit tests for freshness, overall state, feature impacts, and copy payloads | page-level summary consistency assertions |
|
|
| `EvidenceOverviewTableState` | `tests/Feature/Evidence/EvidenceOverviewPageTest.php` | native table assertions and any new table-standard guard alignment |
|
|
| `EvidenceOverviewRow` DB-only invariant | `tests/Feature/Filament/EvidenceOverviewDerivedStateMemoizationTest.php` | update assertions to reflect native table rendering without losing memoization guarantees | |