openapi: 3.1.0 info: title: Workspace Baseline Compare Matrix Internal Surface Contract version: 0.1.0 summary: Internal logical contract for workspace baseline compare matrix reads, drilldown context, and compare-all launch behavior description: | This contract is an internal planning artifact for Spec 190. The affected routes still render HTML through Filament and Livewire. The schemas below define the bounded read models and action payloads that must be derivable from existing baseline, compare, finding, and run truth before the matrix surface can render or trigger compare-all. servers: - url: /internal x-baseline-compare-matrix-consumers: - surface: baseline.profile.detail sourceFiles: - apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php mustRender: - baseline_profile_id - reference_snapshot_id - visible_tenant_count - open_compare_matrix_action - compare_assigned_tenants_action - surface: baseline.compare.matrix sourceFiles: - apps/platform/app/Filament/Pages/BaselineCompareMatrix.php - apps/platform/resources/views/filament/pages/baseline-compare-matrix.blade.php mustRender: - reference - filters - tenant_summaries - subject_summaries - matrix_rows - freshness_legend - trust_legend mustAccept: - policy_type - state - severity - tenant_sort - subject_sort - subject_key - surface: tenant.compare.drilldown sourceFiles: - apps/platform/app/Filament/Pages/BaselineCompareLanding.php - apps/platform/app/Support/Navigation/CanonicalNavigationContext.php mustRender: - matrix_source_context - baseline_profile_id - subject_key - back_link paths: /admin/baseline-profiles/{profile}/compare-matrix: get: summary: Render the workspace baseline compare matrix for one selected baseline profile operationId: viewBaselineCompareMatrix parameters: - name: profile in: path required: true schema: type: integer - name: policy_type in: query required: false schema: type: array items: type: string - name: state in: query required: false schema: type: array items: $ref: '#/components/schemas/MatrixCellState' - name: severity in: query required: false schema: type: array items: $ref: '#/components/schemas/FindingSeverity' - name: tenant_sort in: query required: false schema: $ref: '#/components/schemas/TenantSort' - name: subject_sort in: query required: false schema: $ref: '#/components/schemas/SubjectSort' - name: subject_key in: query required: false schema: type: string description: Optional focused subject row selector for subject-first drilldown within the same matrix route. responses: '200': description: Rendered workspace matrix plus a fully derived matrix bundle content: text/html: schema: type: string application/vnd.tenantpilot.baseline-compare-matrix+json: schema: $ref: '#/components/schemas/BaselineCompareMatrixBundle' '403': description: Actor is in scope but lacks workspace baseline view capability '404': description: Workspace or baseline profile is outside actor scope /internal/workspaces/{workspace}/baseline-profiles/{profile}/compare-assigned-tenants: post: summary: Launch compare for all visible assigned tenants under the selected baseline profile operationId: compareAssignedTenants parameters: - name: workspace in: path required: true schema: type: integer - name: profile in: path required: true schema: type: integer responses: '200': description: Compare-all launch summary derived from underlying tenant compare starts content: application/vnd.tenantpilot.compare-assigned-tenants+json: schema: $ref: '#/components/schemas/CompareAssignedTenantsLaunchResult' '403': description: Actor is in scope but lacks workspace baseline manage capability '404': description: Workspace or baseline profile is outside actor scope components: schemas: MatrixCellState: type: string enum: - match - differ - missing - ambiguous - not_compared - stale_result FindingSeverity: type: string enum: - low - medium - high - critical FreshnessState: type: string enum: - fresh - stale - never_compared - unknown TrustLevel: type: string enum: - trustworthy - limited_confidence - diagnostic_only - unusable TenantSort: type: string enum: - tenant_name - deviation_count - freshness_urgency SubjectSort: type: string enum: - deviation_breadth - policy_type - display_name MatrixReference: type: object additionalProperties: false required: - workspaceId - baselineProfileId - baselineProfileName - baselineStatus - referenceState - assignedTenantCount - visibleTenantCount properties: workspaceId: type: integer baselineProfileId: type: integer baselineProfileName: type: string baselineStatus: type: string referenceSnapshotId: type: - integer - 'null' referenceSnapshotCapturedAt: type: - string - 'null' format: date-time referenceState: type: string referenceReasonCode: type: - string - 'null' assignedTenantCount: type: integer visibleTenantCount: type: integer MatrixTenantSummary: type: object additionalProperties: false required: - tenantId - tenantName - freshnessState - matchedCount - differingCount - missingCount - ambiguousCount - notComparedCount - trustLevel properties: tenantId: type: integer tenantName: type: string compareRunId: type: - integer - 'null' compareRunStatus: type: - string - 'null' compareRunOutcome: type: - string - 'null' freshnessState: $ref: '#/components/schemas/FreshnessState' lastComparedAt: type: - string - 'null' format: date-time matchedCount: type: integer differingCount: type: integer missingCount: type: integer ambiguousCount: type: integer notComparedCount: type: integer maxSeverity: anyOf: - $ref: '#/components/schemas/FindingSeverity' - type: 'null' trustLevel: $ref: '#/components/schemas/TrustLevel' MatrixSubjectSummary: type: object additionalProperties: false required: - subjectKey - policyType - deviationBreadth - missingBreadth - ambiguousBreadth - notComparedBreadth - trustLevel properties: subjectKey: type: string policyType: type: string displayName: type: - string - 'null' baselineExternalId: type: - string - 'null' deviationBreadth: type: integer missingBreadth: type: integer ambiguousBreadth: type: integer notComparedBreadth: type: integer maxSeverity: anyOf: - $ref: '#/components/schemas/FindingSeverity' - type: 'null' trustLevel: $ref: '#/components/schemas/TrustLevel' MatrixCell: type: object additionalProperties: false required: - tenantId - subjectKey - state - trustLevel - policyTypeCovered properties: tenantId: type: integer subjectKey: type: string state: $ref: '#/components/schemas/MatrixCellState' severity: anyOf: - $ref: '#/components/schemas/FindingSeverity' - type: 'null' trustLevel: $ref: '#/components/schemas/TrustLevel' reasonCode: type: - string - 'null' compareRunId: type: - integer - 'null' findingId: type: - integer - 'null' findingWorkflowState: type: - string - 'null' lastComparedAt: type: - string - 'null' format: date-time policyTypeCovered: type: boolean MatrixRow: type: object additionalProperties: false required: - subject - cells properties: subject: $ref: '#/components/schemas/MatrixSubjectSummary' cells: type: array items: $ref: '#/components/schemas/MatrixCell' MatrixFilterState: type: object additionalProperties: false properties: policyTypes: type: array items: type: string states: type: array items: $ref: '#/components/schemas/MatrixCellState' severities: type: array items: $ref: '#/components/schemas/FindingSeverity' tenantSort: $ref: '#/components/schemas/TenantSort' subjectSort: $ref: '#/components/schemas/SubjectSort' focusedSubjectKey: type: - string - 'null' BaselineCompareMatrixBundle: type: object additionalProperties: false required: - reference - filters - tenantSummaries - subjectSummaries - rows properties: reference: $ref: '#/components/schemas/MatrixReference' filters: $ref: '#/components/schemas/MatrixFilterState' tenantSummaries: type: array items: $ref: '#/components/schemas/MatrixTenantSummary' subjectSummaries: type: array items: $ref: '#/components/schemas/MatrixSubjectSummary' rows: type: array items: $ref: '#/components/schemas/MatrixRow' CompareAssignedTenantTarget: type: object additionalProperties: false required: - tenantId - launchState properties: tenantId: type: integer runId: type: - integer - 'null' launchState: type: string enum: - queued - already_queued - blocked reasonCode: type: - string - 'null' CompareAssignedTenantsLaunchResult: type: object additionalProperties: false required: - baselineProfileId - visibleAssignedTenantCount - queuedCount - alreadyQueuedCount - blockedCount - targets properties: baselineProfileId: type: integer visibleAssignedTenantCount: type: integer queuedCount: type: integer alreadyQueuedCount: type: integer blockedCount: type: integer targets: type: array items: $ref: '#/components/schemas/CompareAssignedTenantTarget'