syncDefaults(); }); it('Spec435 readiness evaluation remains in-memory and creates no resources evidence or operation runs', function (): void { $beforeRuns = OperationRun::query()->count(); $readiness = app(ExchangePowerShellEvidenceNormalizer::class)->evaluate( spec435FeatureEnvelope('transportRule', [[ 'Guid' => 'rule-guid-1', 'DisplayName' => 'Rule 1', 'Enabled' => true, ]]), ); expect($readiness->ready)->toBeTrue() ->and(OperationRun::query()->count())->toBe($beforeRuns) ->and(TenantConfigurationResource::query()->count())->toBe(0) ->and(TenantConfigurationResourceEvidence::query()->count())->toBe(0); }); it('Spec435 empty collections create no durable collection proof resource or evidence row', function (): void { $readiness = app(ExchangePowerShellEvidenceNormalizer::class)->evaluate( spec435FeatureEnvelope('transportRule', [], 'empty_collection'), ); expect($readiness->ready)->toBeTrue() ->and($readiness->emptyCollection)->toBeTrue() ->and($readiness->normalizedPreviews)->toBe([]) ->and($readiness->hashPreviews)->toBe([]) ->and(TenantConfigurationResource::query()->count())->toBe(0) ->and(TenantConfigurationResourceEvidence::query()->count())->toBe(0); }); it('Spec435 readiness code stays separated from capture upsert and evidence append paths', function (): void { $runtimeSource = collect(spec435RuntimeFiles()) ->map(fn (string $file): string => file_get_contents($file) ?: '') ->implode("\n"); expect($runtimeSource) ->not->toContain('ExchangePowerShellEvidenceCaptureAdapter::capture') ->not->toContain('CoverageResourceUpserter') ->not->toContain('CoverageEvidenceWriter') ->not->toContain('TenantConfigurationResourceEvidence::') ->not->toContain('content_backed') ->not->toContain('comparable') ->not->toContain('renderable') ->not->toContain('certified') ->not->toContain('restore_ready') ->not->toContain('customer_ready'); }); it('Spec435 introduces no product surface triggers migrations tenant-id ownership or mini-platform', function (): void { $runtimeSource = collect(spec435RuntimeFiles()) ->map(fn (string $file): string => file_get_contents($file) ?: '') ->implode("\n"); expect(preg_match('/\btenant_id\b/', $runtimeSource))->toBe(0) ->and(Schema::hasColumn('tenant_configuration_resources', 'tenant_id'))->toBeFalse() ->and(Schema::hasColumn('tenant_configuration_resource_evidence', 'tenant_id'))->toBeFalse() ->and(glob(app_path('Filament/**/*ExchangePowerShell*')) ?: [])->toBe([]) ->and(glob(app_path('Livewire/**/*ExchangePowerShell*')) ?: [])->toBe([]) ->and(glob(base_path('routes/*exchange*')) ?: [])->toBe([]) ->and(glob(resource_path('views/**/*ExchangePowerShell*')) ?: [])->toBe([]) ->and(glob(database_path('migrations/*exchange*evidence*')) ?: [])->toBe([]) ->and(glob(database_path('migrations/*tenant*configuration*exchange*')) ?: [])->toBe([]) ->and(File::exists(app_path('Jobs/TenantConfiguration/CaptureExchangePowerShellEvidenceJob.php')))->toBeFalse() ->and(File::exists(app_path('Jobs/TenantConfiguration/NormalizeExchangePowerShellEvidenceJob.php')))->toBeFalse() ->and(File::exists(app_path('Console/Commands/CaptureExchangePowerShellEvidence.php')))->toBeFalse(); }); function spec435FeatureEnvelope( string $canonicalType, array $items, string $outputState = 'structured_collection', ): ExchangePowerShellStructuredOutputEnvelope { return ExchangePowerShellStructuredOutputEnvelope::fromInvocationResult( resourceType: $canonicalType, contract: spec435FeatureVerifiedContract($canonicalType), runnerMode: 'fake', result: ExchangePowerShellInvocationResult::succeeded($items, context: [ 'output_state' => $outputState, 'item_count' => count($items), ]), ); } function spec435FeatureVerifiedContract(string $canonicalType): ExchangePowerShellCommandContract { $contracts = new ExchangePowerShellCommandContracts; $contract = $contracts->contractForCanonicalType($canonicalType); if (! is_array($contract)) { throw new RuntimeException('Missing Spec435 feature command contract.'); } return ExchangePowerShellCommandContract::fromVerifiedArray($contract, $contracts, []); } /** * @return list */ function spec435RuntimeFiles(): array { return [ app_path('Services/TenantConfiguration/ExchangePowerShellStructuredOutputEnvelope.php'), app_path('Services/TenantConfiguration/ExchangePowerShellEvidenceNormalizer.php'), app_path('Services/TenantConfiguration/ExchangePowerShellTargetEvidenceNormalizer.php'), app_path('Services/TenantConfiguration/ExchangeTransportRuleEvidenceNormalizer.php'), app_path('Services/TenantConfiguration/ExchangeRemoteDomainEvidenceNormalizer.php'), app_path('Services/TenantConfiguration/ExchangeInboundConnectorEvidenceNormalizer.php'), app_path('Services/TenantConfiguration/ExchangePowerShellNormalizerReadiness.php'), app_path('Services/TenantConfiguration/ExchangePowerShellHashInputBuilder.php'), ]; }