active()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'capture_mode' => BaselineCaptureMode::Opportunistic->value, 'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], ]); InventoryItem::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'external_id' => 'audit-policy-a', 'policy_type' => 'deviceConfiguration', 'display_name' => 'Audit policy A', 'meta_jsonb' => ['odata_type' => '#microsoft.graph.deviceConfiguration', 'etag' => 'E_AUDIT'], ]); $operationRunService = app(OperationRunService::class); $run = $operationRunService->ensureRunWithIdentity( tenant: $tenant, type: 'baseline_capture', identityInputs: ['baseline_profile_id' => (int) $profile->getKey()], context: [ 'baseline_profile_id' => (int) $profile->getKey(), 'source_tenant_id' => (int) $tenant->getKey(), 'effective_scope' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], ], initiator: $user, ); (new CaptureBaselineSnapshotJob($run))->handle( app(BaselineSnapshotIdentity::class), app(InventoryMetaContract::class), app(AuditLogger::class), $operationRunService, ); $started = AuditLog::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('action', 'baseline.capture.started') ->latest('id') ->first(); $completed = AuditLog::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('action', 'baseline.capture.completed') ->latest('id') ->first(); expect($started)->not->toBeNull(); expect($completed)->not->toBeNull(); expect($started?->summaryText())->toContain('Baseline capture started') ->and($started?->normalizedOutcome())->toBe(AuditOutcome::Success) ->and($started?->actorSnapshot()->type)->toBe(AuditActorType::Human) ->and($started?->targetDisplayLabel())->toBe($profile->name) ->and((int) $started?->operation_run_id)->toBe((int) $run->getKey()); expect($completed?->summaryText())->toContain('Baseline capture completed') ->and($completed?->normalizedOutcome())->toBe(AuditOutcome::Success) ->and($completed?->actorSnapshot()->type)->toBe(AuditActorType::Human) ->and($completed?->targetDisplayLabel())->not->toBeNull() ->and((int) $completed?->operation_run_id)->toBe((int) $run->getKey()); }); it('records no-data baseline capture audit metadata without claiming baseline truth changed', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $profile = BaselineProfile::factory()->active()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'capture_mode' => BaselineCaptureMode::Opportunistic->value, 'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], ]); $inventorySyncRun = createInventorySyncOperationRunWithCoverage($tenant, [ 'deviceConfiguration' => 'succeeded', ]); $operationRunService = app(OperationRunService::class); $run = $operationRunService->ensureRunWithIdentity( tenant: $tenant, type: 'baseline_capture', identityInputs: ['baseline_profile_id' => (int) $profile->getKey()], context: [ 'baseline_profile_id' => (int) $profile->getKey(), 'source_tenant_id' => (int) $tenant->getKey(), 'effective_scope' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []], 'baseline_capture' => [ 'inventory_sync_run_id' => (int) $inventorySyncRun->getKey(), 'eligibility' => [ 'phase' => 'preflight', 'ok' => true, 'inventory_sync_run_id' => (int) $inventorySyncRun->getKey(), 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], ], ], ], initiator: $user, ); (new CaptureBaselineSnapshotJob($run))->handle( app(BaselineSnapshotIdentity::class), app(InventoryMetaContract::class), app(AuditLogger::class), $operationRunService, ); $completed = AuditLog::query() ->where('tenant_id', (int) $tenant->getKey()) ->where('action', 'baseline.capture.completed') ->latest('id') ->first(); expect($completed)->not->toBeNull(); expect(data_get($completed?->metadata, 'reason_code'))->toBe(BaselineReasonCodes::CAPTURE_ZERO_SUBJECTS); expect(data_get($completed?->metadata, 'current_baseline_changed'))->toBeFalse(); expect(data_get($completed?->metadata, 'snapshot_id'))->not->toBeNull(); });