providerResource($identity) ->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'canonical_subject_key' => $canonicalSubjectKey, 'display_label' => $displayName, 'resolution_mode' => ProviderResourceResolutionMode::ManualBinding->value, ]); BaselineSnapshotItem::factory()->create([ 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'subject_type' => 'policy', 'subject_external_id' => BaselineSubjectKey::workspaceSafeSubjectExternalId('deviceConfiguration', $canonicalSubjectKey), 'subject_key' => $canonicalSubjectKey, 'policy_type' => 'deviceConfiguration', 'baseline_hash' => app(BaselineSnapshotIdentity::class)->hashItemContent('deviceConfiguration', 'bound-policy-2', $currentMeta), 'meta_jsonb' => $currentMeta, ]); $inventorySyncRun = createInventorySyncOperationRunWithCoverage( tenant: $tenant, statusByType: ['deviceConfiguration' => 'succeeded'], ); spec382CompareInventoryItem( tenant: $tenant, identity: ResourceIdentity::providerResource('fake-provider', 'policy', 'bound-policy-1'), externalId: 'bound-policy-1', displayName: $displayName, etag: 'etag-bound-policy-1', inventorySyncRunId: (int) $inventorySyncRun->getKey(), ); spec382CompareInventoryItem( tenant: $tenant, identity: $identity, externalId: 'bound-policy-2', displayName: $displayName, etag: 'etag-bound-policy-2', inventorySyncRunId: (int) $inventorySyncRun->getKey(), ); $run = spec382RunCompare($tenant, $user, $profile, $snapshot); $run->refresh(); $context = is_array($run->context) ? $run->context : []; expect($run->outcome)->toBe(OperationRunOutcome::Succeeded->value) ->and(data_get($context, 'baseline_compare.matching.active_bindings_considered'))->toBe(1) ->and(data_get($context, 'baseline_compare.matching.by_reason.active_provider_resource_binding'))->toBe(1) ->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.ambiguous_match'))->toBeNull() ->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.identity_required'))->toBeNull() ->and(Finding::query() ->where('managed_environment_id', (int) $tenant->getKey()) ->where('source', 'baseline.compare') ->where('subject_external_id', 'bound-policy-2') ->exists())->toBeFalse(); }); it('turns old subject-key and display-only baseline subjects into identity-required gaps', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $displayName = 'Display Only Match Policy'; [$profile, $snapshot] = spec382CompareProfileAndSnapshot($tenant); $meta = [ 'display_name' => $displayName, 'etag' => 'display-only-etag', ]; BaselineSnapshotItem::factory()->create([ 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'subject_type' => 'policy', 'subject_external_id' => BaselineSubjectKey::workspaceSafeSubjectExternalId('deviceConfiguration', 'old-display-subject-key'), 'subject_key' => 'old-display-subject-key', 'policy_type' => 'deviceConfiguration', 'baseline_hash' => app(BaselineSnapshotIdentity::class)->hashItemContent('deviceConfiguration', 'display-only-policy', $meta), 'meta_jsonb' => $meta, ]); $inventorySyncRun = createInventorySyncOperationRunWithCoverage( tenant: $tenant, statusByType: ['deviceConfiguration' => 'succeeded'], ); InventoryItem::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'external_id' => 'display-only-policy', 'policy_type' => 'deviceConfiguration', 'display_name' => $displayName, 'meta_jsonb' => $meta, 'last_seen_operation_run_id' => (int) $inventorySyncRun->getKey(), 'last_seen_at' => now(), ]); $run = spec382RunCompare($tenant, $user, $profile, $snapshot); $run->refresh(); $context = is_array($run->context) ? $run->context : []; expect($run->outcome)->toBe(OperationRunOutcome::PartiallySucceeded->value) ->and(data_get($context, 'baseline_compare.matching.by_reason.identity_required'))->toBe(1) ->and(data_get($context, 'baseline_compare.evidence_gaps.by_reason.identity_required'))->toBe(1) ->and(data_get($context, 'baseline_compare.matching.by_reason.canonical_subject_key'))->toBeNull(); }); function spec382CompareProfileAndSnapshot($tenant): array { $profile = BaselineProfile::factory()->active()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], ]); $snapshot = BaselineSnapshot::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'baseline_profile_id' => (int) $profile->getKey(), 'captured_at' => now()->subMinute(), ]); $profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]); return [$profile, $snapshot]; } function spec382CompareSubjectKey(ResourceIdentity $identity): string { $subjectKey = BaselineSubjectKey::forProviderResourceIdentity( subjectDomain: 'baseline', subjectClass: SubjectClass::PolicyBacked, subjectTypeKey: 'deviceConfiguration', identity: $identity, ); expect($subjectKey)->not->toBeNull(); return (string) $subjectKey; } function spec382CompareMeta(ResourceIdentity $identity, string $displayName, string $etag): array { return [ 'display_name' => $displayName, 'provider_key' => $identity->providerKey, 'provider_resource_identity' => $identity->toArray(), 'provider_resource_fingerprint' => $identity->fingerprint(), 'odata_type' => 'fake.policy', 'etag' => $etag, ]; } function spec382CompareInventoryItem( $tenant, ResourceIdentity $identity, string $externalId, string $displayName, string $etag, int $inventorySyncRunId, ): InventoryItem { return InventoryItem::factory()->create([ 'managed_environment_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'external_id' => $externalId, 'policy_type' => 'deviceConfiguration', 'display_name' => $displayName, 'meta_jsonb' => spec382CompareMeta($identity, $displayName, $etag), 'last_seen_operation_run_id' => $inventorySyncRunId, 'last_seen_at' => now(), ]); } function spec382RunCompare($tenant, $user, BaselineProfile $profile, BaselineSnapshot $snapshot) { $operationRunService = app(OperationRunService::class); $run = $operationRunService->ensureRunWithIdentity( tenant: $tenant, type: OperationRunType::BaselineCompare->value, identityInputs: ['baseline_profile_id' => (int) $profile->getKey()], context: [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'effective_scope' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], ], initiator: $user, ); (new CompareBaselineToTenantJob($run))->handle( app(BaselineSnapshotIdentity::class), app(AuditLogger::class), $operationRunService, ); return $run; }