cache->put('ext.cache_version', ...)` 가 플러그인 * 도메인으로 누수되어 화면에 반영되지 않는 결함이 재발한다. * * 본 테스트는 코어 컨텍스트에서 모든 ServiceProvider 가 부팅된 직후의 상태를 검증한다. * 플러그인별 contextual binding 정확성 (식별자 prefix 매칭 등) 은 해당 플러그인의 * Feature 테스트로 검증한다 (예: PluginCacheContextualBindingTest in * plugins/_bundled/sirsoft-verification_kginicis/tests/Feature/). * * @see tests/scenarios/extension-cache-binding-isolation.yaml */ class PluginCacheBindingIsolationTest extends TestCase { /** * @scenario extension_kind=plugin,service_kind=cache_service,global_binding_state=installed_before_provider,manager_state=plugin_resolved,consumer_type=single_class * @effects global_cache_interface_binding_remains_core_cache_driver */ public function test_global_cache_interface_resolves_to_core_cache_driver(): void { $cache = $this->app->make(CacheInterface::class); $this->assertInstanceOf( CoreCacheDriver::class, $cache, 'app(CacheInterface) 는 항상 CoreCacheDriver 여야 한다. ' .'PluginCacheDriver 가 반환되면 어떤 ServiceProvider 가 ' .'$this->app->singleton(CacheInterface::class, ...) 로 글로벌 바인딩을 덮어쓰고 있다 (이슈 #392).' ); } /** * @scenario extension_kind=plugin,service_kind=storage_service,global_binding_state=absent,manager_state=plugin_resolved,consumer_type=no_registration * @effects global_storage_interface_binding_remains_core_storage_driver */ public function test_global_storage_interface_is_not_bound_to_extension_driver(): void { // 코어는 StorageInterface 를 글로벌 바인딩하지 않는다 — 확장은 contextual binding // 으로만 StorageInterface 를 주입해야 한다. 어떤 ServiceProvider 가 글로벌 // 바인딩을 등록했다면 그 자체가 결함 후보 (특히 확장 도메인 드라이버로 바인딩 시 // 코어/타 확장 도메인의 파일 접근이 누수됨). if (! $this->app->bound(StorageInterface::class)) { $this->assertTrue(true, 'StorageInterface 는 글로벌 바인딩이 없는 상태가 정상.'); return; } $storage = $this->app->make(StorageInterface::class); $this->assertNotInstanceOf( \App\Extension\Storage\PluginStorageDriver::class, $storage, 'app(StorageInterface) 는 PluginStorageDriver 가 아니어야 한다 — 확장 ServiceProvider 의 글로벌 재바인딩 의심.' ); $this->assertNotInstanceOf( \App\Extension\Storage\ModuleStorageDriver::class, $storage, 'app(StorageInterface) 는 ModuleStorageDriver 가 아니어야 한다 — 확장 ServiceProvider 의 글로벌 재바인딩 의심.' ); } /** * @scenario extension_kind=plugin,service_kind=cache_service,global_binding_state=installed_before_provider,manager_state=plugin_resolved,consumer_type=single_class * @effects layout_service_ext_cache_version_key_written_to_core_namespace */ public function test_core_cache_writes_use_core_namespace_prefix(): void { $cache = $this->app->make(CacheInterface::class); $this->assertInstanceOf(CoreCacheDriver::class, $cache); $resolvedKey = $cache->resolveKey('ext.cache_version'); $this->assertStringStartsWith( 'g7:core:', $resolvedKey, '코어 LayoutService 의 ext.cache_version bump 가 플러그인 도메인 (g7:plugin.*:) 으로 누수되면 안 된다.' ); // 실제 put → has → forget 사이클로 코어 캐시 도메인이 정상 동작함을 검증 $cache->put('isolation_probe_392', 'probe', 60); $this->assertTrue($cache->has('isolation_probe_392')); $cache->forget('isolation_probe_392'); } }