openapi: 3.1.0
info:
  title: Filament Nativity Cleanup Logical Contract
  version: 0.1.0
  description: >-
    Logical planning contract for Spec 196. This artifact defines the expected
    state ownership, filter semantics, scope guarantees, and row projections for
    the three cleaned UI surfaces. It is not a runtime API definition.
servers:
  - url: https://logical-spec.local
    description: Non-runtime planning contract
paths:
  /internal/ui/inventory-items/{inventoryItemId}/dependencies:
    get:
      summary: Read dependency section state for one inventory item detail surface
      operationId: getInventoryItemDependenciesView
      parameters:
        - name: inventoryItemId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Dependency detail-surface state and rows
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/DependencyEdgesView'
        '404':
          description: Returned when the actor is not entitled to the tenant or inventory-item scope.
  /internal/ui/tenants/{tenantExternalId}/required-permissions:
    get:
      summary: Read required-permissions page state for one route-scoped tenant
      operationId: getTenantRequiredPermissionsView
      parameters:
        - name: tenantExternalId
          in: path
          required: true
          schema:
            type: string
        - name: status
          in: query
          required: false
          schema:
            $ref: '#/components/schemas/RequiredPermissionsStatus'
        - name: type
          in: query
          required: false
          schema:
            $ref: '#/components/schemas/PermissionTypeFilter'
        - name: features
          in: query
          required: false
          schema:
            type: array
            items:
              type: string
        - name: search
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Required-permissions page state, summary, and rows
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/RequiredPermissionsView'
        '404':
          description: Returned when workspace or tenant membership is absent for the route-scoped tenant.
  /internal/ui/evidence-overview:
    get:
      summary: Read workspace evidence overview table state and rows
      operationId: getEvidenceOverviewView
      parameters:
        - name: tenantId
          in: query
          required: false
          description: Optional entitled tenant prefilter; unauthorized tenant identifiers must not reveal row existence.
          schema:
            anyOf:
              - type: integer
              - type: 'null'
        - name: search
          in: query
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Workspace evidence overview state and rows
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/EvidenceOverviewView'
        '404':
          description: Returned when workspace membership is absent for the evidence overview surface.
components:
  schemas:
    DependencyDirection:
      type: string
      enum:
        - all
        - inbound
        - outbound
    RelationshipTypeKey:
      type: string
      description: Recognized relationship type key from the existing dependency domain.
    RequiredPermissionsStatus:
      type: string
      enum:
        - missing
        - present
        - error
        - all
    PermissionTypeFilter:
      type: string
      enum:
        - all
        - application
        - delegated
    DependencyEdgesState:
      type: object
      required:
        - inventoryItemId
        - tenantId
        - direction
      properties:
        inventoryItemId:
          type: integer
        tenantId:
          type: integer
        direction:
          $ref: '#/components/schemas/DependencyDirection'
        relationshipType:
          anyOf:
            - $ref: '#/components/schemas/RelationshipTypeKey'
            - type: 'null'
    DependencyEdgeRow:
      type: object
      required:
        - relationshipType
        - targetType
        - renderedTarget
        - isMissing
        - missingTitle
      properties:
        relationshipType:
          type: string
        targetType:
          type: string
        targetId:
          anyOf:
            - type: string
            - type: 'null'
        renderedTarget:
          type: object
          additionalProperties: true
        isMissing:
          type: boolean
        missingTitle:
          type: string
    DependencyEdgesView:
      type: object
      required:
        - state
        - rows
      properties:
        state:
          $ref: '#/components/schemas/DependencyEdgesState'
        rows:
          type: array
          items:
            $ref: '#/components/schemas/DependencyEdgeRow'
    RequiredPermissionsState:
      type: object
      required:
        - routeTenantExternalId
        - status
        - type
        - features
        - search
        - routeTenantAuthoritative
        - seededFromQuery
      properties:
        routeTenantExternalId:
          type: string
        status:
          $ref: '#/components/schemas/RequiredPermissionsStatus'
        type:
          $ref: '#/components/schemas/PermissionTypeFilter'
        features:
          type: array
          uniqueItems: true
          description: Normalized unique list of known feature keys.
          items:
            type: string
        search:
          type: string
        routeTenantAuthoritative:
          type: boolean
          const: true
        seededFromQuery:
          type: boolean
    RequiredPermissionsSummary:
      type: object
      required:
        - counts
        - freshness
        - featureImpacts
        - copyPayloads
        - issues
      properties:
        counts:
          type: object
          additionalProperties:
            type: integer
        overall:
          anyOf:
            - type: string
            - type: 'null'
        freshness:
          type: object
          additionalProperties: true
        featureImpacts:
          type: array
          items:
            type: object
            additionalProperties: true
        copyPayloads:
          type: object
          additionalProperties:
            type: string
        issues:
          type: array
          items:
            type: object
            additionalProperties: true
    PermissionReviewRow:
      type: object
      required:
        - permissionKey
        - type
        - status
      properties:
        permissionKey:
          type: string
        type:
          type: string
        status:
          type: string
        description:
          type: string
        features:
          type: array
          items:
            type: string
        details:
          type: object
          additionalProperties: true
    RequiredPermissionsView:
      type: object
      required:
        - state
        - summary
        - rows
      properties:
        state:
          $ref: '#/components/schemas/RequiredPermissionsState'
        summary:
          $ref: '#/components/schemas/RequiredPermissionsSummary'
        rows:
          type: array
          items:
            $ref: '#/components/schemas/PermissionReviewRow'
    EvidenceOverviewState:
      type: object
      required:
        - workspaceId
        - authorizedTenantIds
        - tenantFilter
        - search
        - seededFromQuery
      properties:
        workspaceId:
          type: integer
        authorizedTenantIds:
          type: array
          items:
            type: integer
        tenantFilter:
          anyOf:
            - type: integer
            - type: 'null'
        search:
          type: string
        seededFromQuery:
          type: boolean
    EvidenceOverviewRow:
      type: object
      required:
        - tenantId
        - tenantName
        - snapshotId
        - artifactTruth
        - freshness
        - missingDimensions
        - staleDimensions
        - nextStep
        - viewUrl
      properties:
        tenantId:
          type: integer
        tenantName:
          type: string
        snapshotId:
          type: integer
        artifactTruth:
          type: object
          additionalProperties: true
        freshness:
          type: object
          additionalProperties: true
        generatedAt:
          anyOf:
            - type: string
            - type: 'null'
        missingDimensions:
          type: integer
        staleDimensions:
          type: integer
        nextStep:
          type: string
        viewUrl:
          type: string
    EvidenceOverviewView:
      type: object
      required:
        - state
        - rows
      properties:
        state:
          $ref: '#/components/schemas/EvidenceOverviewState'
        rows:
          type: array
          items:
            $ref: '#/components/schemas/EvidenceOverviewRow'
x-spec-196-notes:
  consumerScope: illustrative core consumers only; Blade views and focused verification files are tracked in plan.md, quickstart.md, and tasks.md
  consumers:
    - apps/platform/app/Filament/Resources/InventoryItemResource.php
    - apps/platform/app/Livewire/InventoryItemDependencyEdgesTable.php
    - apps/platform/app/Filament/Pages/TenantRequiredPermissions.php
    - apps/platform/app/Filament/Pages/Monitoring/EvidenceOverview.php
    - apps/platform/app/Services/Intune/TenantRequiredPermissionsViewModelBuilder.php
    - apps/platform/tests/Feature/InventoryItemDependenciesTest.php
    - apps/platform/tests/Feature/Rbac/TenantRequiredPermissionsTrustedStateTest.php
    - apps/platform/tests/Feature/Evidence/EvidenceOverviewPageTest.php
  invariants:
    - route tenant stays authoritative on required-permissions
    - evidence overview only exposes entitled tenant rows
    - dependency rendering remains tenant-isolated and DB-only
    - cleaned surfaces remain read-only and introduce no new remote runtime calls at render time
    - native Filament or Livewire state remains the primary contract, with no new wrapper or presenter layer introduced only to translate pseudo-native state
    - required-permissions summary counts, freshness, guidance visibility, and copy payload remain derived from the same normalized filter state as the visible rows
    - evidence overview preserves a meaningful empty state, clear-filter affordance when scoped, and one workspace-safe inspect path per authorized row
    - query values may seed initial state but not stay the primary contract
  nonGoals:
    - runtime API exposure
    - new persistence
    - new polling behavior
    - new provider or route families
    - new global or on-demand asset requirements
    - shared wrapper or presenter framework
    - global context shell redesign
    - monitoring page-state architecture rewrite
    - audit log selected-record or inspect duality cleanup
    - finding exceptions queue dual-inspect cleanup
    - baseline compare matrix or other special-visualization work
    - verification report viewer families or onboarding verification report variants
    - normalized diff or settings viewer families
    - restore preview, restore results, or enterprise-detail layout rework
    - raw anchor-to-component link consistency sweeps
    - badge-only, banner-only, or style-only polish work
    - new CI guardrail, review-enforcement, or constitution frameworks