*/ public function resolveByScopeTarget(string $scope, string $target): Collection; /** * key 존재 시 업데이트, 없으면 생성합니다. Seeder/SyncHelper 가 사용하는 upsert 경로. * * @param array $attributes 정책 속성 * @return IdentityPolicy upsert 된 정책 */ public function upsertByKey(array $attributes): IdentityPolicy; /** * key 기준 업데이트 (운영자 UI 편집 경로). * * @param string $key 정책 키 * @param array $attributes 변경할 속성 * @param array $overridesFields user_overrides 에 append 할 필드명들 * @return bool 업데이트 성공 여부 */ public function updateByKey(string $key, array $attributes, array $overridesFields = []): bool; /** * key 기준 삭제 (source_type=admin 인 정책만 허용). * * @param string $key 정책 키 * @return bool 삭제 성공 여부 */ public function deleteByKey(string $key): bool; /** * 정책 모델을 영속화합니다 (Eloquent save 위임). * * upsert/updateByKey 가 다루지 않는 부분 갱신 경로 (예: user_overrides 부분 복원) 에서 사용합니다. * Service 가 모델 객체에 직접 변경을 적용한 뒤 본 메서드로 저장 — Service-Repository 경유 패턴 유지. * * @param IdentityPolicy $policy 영속화할 모델 * @return bool 저장 성공 여부 */ public function save(IdentityPolicy $policy): bool; /** * source_type+source_identifier 에 속하지 않은 stale 정책을 제거합니다. * * @param string $sourceType 'core' | 'module' | 'plugin' | 'admin' * @param string $sourceIdentifier vendor 식별자 (예: sirsoft-ecommerce, core) * @param array $currentKeys 현재 선언된 key 목록 * @return int 삭제된 행 수 */ public function cleanupStale(string $sourceType, string $sourceIdentifier, array $currentKeys): int; /** * source_type+source_identifier 에 속하면서 currentKeys 에 없는 stale 정책을 조회합니다. * * bulk delete(cleanupStale) 와 달리 모델 인스턴스를 반환하므로, 호출 측이 per-model * delete()(deleted 이벤트 발화 — 라우트 스코프 캐시 flush)와 로깅을 수행할 수 있다. * * @param string $sourceType 'core' | 'module' | 'plugin' | 'admin' * @param string $sourceIdentifier vendor 식별자 * @param array $currentKeys 현재 선언된 key 목록 * @return Collection stale 정책 목록 */ public function findStale(string $sourceType, string $sourceIdentifier, array $currentKeys): Collection; /** * 특정 source(확장) 가 등록한 정책 개수를 반환합니다. * * 모듈/플러그인 uninstall 모달의 "삭제될 데이터" 표시에 사용. * * @param string $sourceType 'core' | 'module' | 'plugin' | 'admin' * @param string $sourceIdentifier 확장 식별자 */ public function countBySource(string $sourceType, string $sourceIdentifier): int; /** * 목록 조회 (관리자 S1d DataGrid). * * @param array $filters 필터 조건 * @param int $perPage 페이지 크기 * @return LengthAwarePaginator */ public function search(array $filters, int $perPage = 20); /** * 전체 활성 정책을 반환합니다. * * @return Collection */ public function allEnabled(): Collection; /** * scope='route' 활성 정책을 [target => Collection] 맵으로 반환합니다. * * EnforceIdentityPolicy 미들웨어의 자동 매핑 lookup 진입점으로 사용. 부팅 시 1회 캐싱되며 * IdentityPolicy 모델 saved/deleted 이벤트가 캐시를 즉시 invalidate 합니다. * * brace expansion 지원: target 'api.admin.{modules,plugins}.uninstall' 같은 표현은 * 두 개의 라우트명으로 펼쳐 동일 정책 인스턴스를 양쪽에 매핑합니다. * * @return array> route name → 매칭 정책 컬렉션 */ public function getRouteScopeIndex(): array; /** * scope='hook' 활성 정책의 target 목록(중복 제거)을 반환합니다. * * EnforceIdentityPolicyListener::loadDynamicHookTargets() 가 부팅 시 동적 훅 구독을 위해 * 호출하는 단일 진입점입니다. identity_policies 테이블이 존재하지 않거나 DB 미연결 환경 * (마이그레이션 전 부팅) 에서는 빈 배열을 반환해 부팅을 보호합니다. * * @return list 동적 hook target 목록 */ public function listHookTargets(): array; }