openapi: 3.1.0 info: title: Governance Subject Taxonomy and Baseline Scope V2 Internal Contract version: 0.1.0 summary: Internal logical contract for canonical baseline scope, taxonomy listing, save-forward writes, and normalized baseline operation starts description: | This contract is an internal planning artifact for Spec 202. The affected surfaces still render through Filament and Livewire, and baseline capture or compare continues to run through the existing Laravel services and jobs. The schemas below define the canonical baseline scope document, the governance subject taxonomy registry, legacy normalization behavior, and the effective scope that capture and compare must consume. The path entries below are logical boundary identifiers for existing Filament, Livewire, and service entry points only; they do not imply new HTTP controllers or routes. x-logical-artifact: true x-governance-subject-taxonomy-consumers: - surface: baseline.profile.form sourceFiles: - apps/platform/app/Filament/Resources/BaselineProfileResource.php - apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/CreateBaselineProfile.php - apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/EditBaselineProfile.php mustRender: - normalized_scope_summary - active_subject_groups - support_readiness - invalid_scope_feedback mustAccept: - legacy_scope_input - canonical_scope_v2 - surface: baseline.profile.detail sourceFiles: - apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php mustRender: - canonical_scope_summary - support_readiness - normalization_lineage_on_demand - surface: baseline.scope.backfill.command sourceFiles: - apps/platform/app/Console/Commands/BackfillBaselineScopeV2.php mustAccept: - preview_mode_by_default - explicit_write_confirmation mustProduce: - candidate_rewrite_summary - committed_rewrite_summary - committed_write_audit_logging - surface: baseline.capture.start sourceFiles: - apps/platform/app/Services/Baselines/BaselineCaptureService.php mustConsume: - effective_scope_v2 - capture_eligible_subject_types - compatibility_projection_if_needed - surface: baseline.compare.start sourceFiles: - apps/platform/app/Services/Baselines/BaselineCompareService.php mustConsume: - effective_scope_v2 - compare_eligible_subject_types - compatibility_projection_if_needed paths: /internal/workspaces/{workspace}/governance-subject-taxonomy/baseline-subject-types: get: summary: List active baseline-selectable governance subject types for the current workspace context operationId: listBaselineSubjectTypes parameters: - name: workspace in: path required: true schema: type: integer responses: '200': description: Grouped taxonomy metadata for baseline scope selection and validation content: application/vnd.tenantpilot.governance-taxonomy+json: schema: $ref: '#/components/schemas/GovernanceSubjectTaxonomyRegistry' '403': description: Actor is in scope but lacks workspace baseline view capability '404': description: Workspace is outside actor scope /internal/workspaces/{workspace}/baseline-scope/normalize: post: summary: Normalize legacy or canonical scope input into Baseline Scope V2 operationId: normalizeBaselineScope parameters: - name: workspace in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LegacyOrV2ScopeInput' responses: '200': description: Canonical V2 scope plus summary and validation detail content: application/vnd.tenantpilot.baseline-scope-normalized+json: schema: $ref: '#/components/schemas/BaselineScopeNormalizationResult' '422': description: Scope input is invalid or ambiguous after normalization content: application/vnd.tenantpilot.baseline-scope-errors+json: schema: $ref: '#/components/schemas/BaselineScopeValidationErrors' '403': description: Actor is in scope but lacks workspace baseline manage capability '404': description: Workspace is outside actor scope /internal/workspaces/{workspace}/baseline-scope/backfill: post: summary: Logical maintenance boundary for previewing or committing baseline profile scope backfill operationId: backfillBaselineProfileScopeV2 description: Logical-only maintenance contract for `baseline_profiles.scope_jsonb`; compare assignment overrides remain tolerant-read only in this release. parameters: - name: workspace in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BaselineScopeBackfillRequest' responses: '200': description: Preview or commit summary for the baseline profile scope backfill command content: application/vnd.tenantpilot.baseline-scope-backfill+json: schema: $ref: '#/components/schemas/BaselineScopeBackfillResult' '403': description: Actor is in scope but lacks workspace baseline manage capability '404': description: Workspace is outside actor scope /admin/baseline-profiles: post: summary: Create a baseline profile using a scope request that is canonicalized to V2 before persistence operationId: createBaselineProfileWithCanonicalScope requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BaselineProfileWriteRequest' responses: '201': description: Baseline profile created with canonical V2 scope persisted content: application/vnd.tenantpilot.baseline-profile+json: schema: $ref: '#/components/schemas/BaselineProfileScopeEnvelope' '422': description: Scope validation failed '403': description: Actor is in scope but lacks workspace baseline manage capability '404': description: Workspace is outside actor scope /admin/baseline-profiles/{profile}: patch: summary: Update a baseline profile and save scope forward as canonical V2 operationId: updateBaselineProfileWithCanonicalScope parameters: - name: profile in: path required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BaselineProfileWriteRequest' responses: '200': description: Baseline profile updated with canonical V2 scope persisted content: application/vnd.tenantpilot.baseline-profile+json: schema: $ref: '#/components/schemas/BaselineProfileScopeEnvelope' '422': description: Scope validation failed '403': description: Actor is in scope but lacks workspace baseline manage capability '404': description: Workspace or baseline profile is outside actor scope /internal/tenants/{tenant}/baseline-profiles/{profile}/capture: post: summary: Start baseline capture using normalized effective scope operationId: startBaselineCaptureWithNormalizedScope parameters: - name: tenant in: path required: true schema: type: integer - name: profile in: path required: true schema: type: integer responses: '202': description: Baseline capture accepted with canonical effective scope recorded in operation context content: application/vnd.tenantpilot.baseline-operation+json: schema: $ref: '#/components/schemas/BaselineOperationEnvelope' '422': description: Requested scope is invalid or includes unsupported capture subject types '403': description: Actor is in scope but lacks capability to start capture '404': description: Tenant or profile is outside actor scope /internal/tenants/{tenant}/baseline-profiles/{profile}/compare: post: summary: Start baseline compare using normalized effective scope operationId: startBaselineCompareWithNormalizedScope parameters: - name: tenant in: path required: true schema: type: integer - name: profile in: path required: true schema: type: integer responses: '202': description: Baseline compare accepted with canonical effective scope recorded in operation context content: application/vnd.tenantpilot.baseline-operation+json: schema: $ref: '#/components/schemas/BaselineOperationEnvelope' '422': description: Requested scope is invalid or includes unsupported compare subject types '403': description: Actor is in scope but lacks capability to start compare '404': description: Tenant or profile is outside actor scope components: schemas: GovernanceDomainKey: type: string description: Current active values are `intune` and `platform_foundation`; additional domain keys may be introduced later without changing the V2 contract shape. examples: - intune - platform_foundation - entra GovernanceSubjectClass: type: string enum: - policy - configuration_resource - posture_dimension - control GovernanceSubjectType: type: object additionalProperties: false required: - domain_key - subject_class - subject_type_key - label - description - capture_supported - compare_supported - inventory_supported - active properties: domain_key: $ref: '#/components/schemas/GovernanceDomainKey' subject_class: $ref: '#/components/schemas/GovernanceSubjectClass' subject_type_key: type: string label: type: string description: type: - string - 'null' capture_supported: type: boolean compare_supported: type: boolean inventory_supported: type: boolean active: type: boolean support_mode: type: - string - 'null' legacy_bucket: type: - string - 'null' GovernanceSubjectTaxonomyRegistry: type: object additionalProperties: false required: - subject_types properties: subject_types: type: array items: $ref: '#/components/schemas/GovernanceSubjectType' LegacyBaselineScopePayload: type: object additionalProperties: false minProperties: 1 properties: policy_types: type: array description: Empty or omitted means all supported Intune policy subject types when the other legacy bucket is present. items: type: string foundation_types: type: array description: Empty or omitted means no foundation subject types when the other legacy bucket is present. items: type: string BaselineScopeEntryV2: type: object additionalProperties: false required: - domain_key - subject_class - subject_type_keys properties: domain_key: $ref: '#/components/schemas/GovernanceDomainKey' subject_class: $ref: '#/components/schemas/GovernanceSubjectClass' subject_type_keys: type: array minItems: 1 items: type: string filters: type: object additionalProperties: true default: {} BaselineScopeDocumentV2: type: object additionalProperties: false required: - version - entries properties: version: type: integer enum: - 2 entries: type: array minItems: 1 items: $ref: '#/components/schemas/BaselineScopeEntryV2' LegacyOrV2ScopeInput: oneOf: - $ref: '#/components/schemas/LegacyBaselineScopePayload' - $ref: '#/components/schemas/BaselineScopeDocumentV2' BaselineScopeSummaryGroup: type: object additionalProperties: false required: - domain_key - subject_class - group_label - selected_subject_types - capture_supported_count - compare_supported_count properties: domain_key: $ref: '#/components/schemas/GovernanceDomainKey' subject_class: $ref: '#/components/schemas/GovernanceSubjectClass' group_label: type: string selected_subject_types: description: Operator-facing selected subject labels for the group, not raw subject type keys. type: array items: type: string capture_supported_count: type: integer compare_supported_count: type: integer inactive_count: type: integer BaselineScopeNormalizationResult: type: object additionalProperties: false required: - canonical_scope - normalization_lineage - summary properties: canonical_scope: $ref: '#/components/schemas/BaselineScopeDocumentV2' normalization_lineage: $ref: '#/components/schemas/BaselineScopeNormalizationLineage' summary: type: array items: $ref: '#/components/schemas/BaselineScopeSummaryGroup' legacy_projection: type: - object - 'null' additionalProperties: type: array items: type: string BaselineScopeValidationError: type: object additionalProperties: false required: - code - message properties: code: type: string message: type: string path: type: - string - 'null' BaselineScopeValidationErrors: type: object additionalProperties: false required: - errors properties: errors: type: array items: $ref: '#/components/schemas/BaselineScopeValidationError' BaselineProfileWriteRequest: type: object additionalProperties: false required: - name - status - capture_mode - requested_scope properties: name: type: string description: type: - string - 'null' status: type: string capture_mode: type: string version_label: type: - string - 'null' requested_scope: $ref: '#/components/schemas/LegacyOrV2ScopeInput' BaselineProfileScopeEnvelope: type: object additionalProperties: false required: - profile_id - persisted_scope - normalization_lineage - summary properties: profile_id: type: integer persisted_scope: $ref: '#/components/schemas/BaselineScopeDocumentV2' normalization_lineage: $ref: '#/components/schemas/BaselineScopeNormalizationLineage' summary: type: array items: $ref: '#/components/schemas/BaselineScopeSummaryGroup' BaselineScopeNormalizationLineage: type: object additionalProperties: false required: - source_shape - normalized_on_read - legacy_keys_present - save_forward_required properties: source_shape: type: string enum: - legacy - canonical_v2 normalized_on_read: type: boolean legacy_keys_present: type: array items: type: string save_forward_required: type: boolean EffectiveBaselineScope: type: object additionalProperties: false required: - canonical_scope - selected_type_keys - allowed_type_keys - limited_type_keys - unsupported_type_keys properties: canonical_scope: $ref: '#/components/schemas/BaselineScopeDocumentV2' selected_type_keys: type: array items: type: string allowed_type_keys: type: array items: type: string limited_type_keys: type: array items: type: string unsupported_type_keys: type: array items: type: string capabilities_by_type: type: object additionalProperties: true legacy_projection: type: - object - 'null' additionalProperties: type: array items: type: string BaselineOperationEnvelope: type: object additionalProperties: false required: - profile_id - tenant_id - operation_type - effective_scope properties: profile_id: type: integer tenant_id: type: integer operation_type: type: string enum: - baseline_capture - baseline_compare effective_scope: $ref: '#/components/schemas/EffectiveBaselineScope' run_id: type: - integer - 'null' BaselineScopeBackfillRequest: type: object additionalProperties: false required: - dry_run properties: dry_run: type: boolean default: true write_confirmed: type: boolean default: false BaselineScopeBackfillResult: type: object additionalProperties: false required: - mode - candidate_count - rewritten_count - audit_logged - scope_surface properties: mode: type: string enum: - preview - commit candidate_count: type: integer rewritten_count: type: integer audit_logged: type: boolean scope_surface: type: string enum: - baseline_profiles_only