[ // 업로드 'upload_max_file_size_min' => 1, 'upload_max_file_size_max' => 1024, 'upload_image_max_width_min' => 100, 'upload_image_max_width_max' => 10000, 'upload_image_max_height_min' => 100, 'upload_image_max_height_max' => 10000, 'upload_image_quality_min' => 1, 'upload_image_quality_max' => 100, 'upload_orphan_retention_days_min' => 1, 'upload_orphan_retention_days_max' => 3650, // SEO 'seo_og_image_default_width_min' => 0, 'seo_og_image_default_width_max' => 8000, 'seo_og_image_default_height_min' => 0, 'seo_og_image_default_height_max' => 8000, 'seo_cache_ttl_min' => 60, 'seo_cache_ttl_max' => 86400, 'seo_sitemap_cache_ttl_min' => 3600, 'seo_sitemap_cache_ttl_max' => 604800, 'seo_sitemap_urls_per_file_min' => 1000, 'seo_sitemap_urls_per_file_max' => 50000, // 보안 'security_password_min_length_min' => 6, 'security_password_min_length_max' => 64, 'security_auth_token_lifetime_min' => 0, 'security_auth_token_lifetime_max' => 3600, 'security_max_login_attempts_min' => 0, 'security_max_login_attempts_max' => 100, 'security_login_lockout_time_min' => 0, 'security_login_lockout_time_max' => 1440, // 고급 (캐시 TTL) 'advanced_cache_ttl_min' => 0, 'advanced_cache_ttl_max' => 14400, 'advanced_seo_sitemap_cache_ttl_min' => 3600, 'advanced_seo_sitemap_cache_ttl_max' => 604800, // 드라이버 'drivers_redis_port_min' => 1, 'drivers_redis_port_max' => 65535, 'drivers_redis_database_min' => 0, 'drivers_redis_database_max' => 15, 'drivers_memcached_port_min' => 1, 'drivers_memcached_port_max' => 65535, 'drivers_session_lifetime_min' => 1, 'drivers_session_lifetime_max' => 43200, 'drivers_websocket_port_min' => 1, 'drivers_websocket_port_max' => 65535, 'drivers_websocket_server_port_min' => 1, 'drivers_websocket_server_port_max' => 65535, 'drivers_log_days_min' => 1, 'drivers_log_days_max' => 365, // 본인인증 'identity_challenge_ttl_minutes_min' => 1, 'identity_challenge_ttl_minutes_max' => 1440, 'identity_max_attempts_min' => 1, 'identity_max_attempts_max' => 20, // 목록 한계값 (0 = 무제한) 'advanced_pagination_result_cap_min' => 0, 'advanced_pagination_result_cap_max' => 1000000, 'advanced_pagination_max_page_min' => 0, 'advanced_pagination_max_page_max' => 100000, ], /* |-------------------------------------------------------------------------- | 목록 한계값 기본값 |-------------------------------------------------------------------------- | 관리자 환경설정(`pagination` 카테고리)이 비어 있을 때 쓰는 코드 기본값입니다. | 실제 해석은 App\Support\Query\PaginationLimits 가 단독으로 수행하며, 확장은 | 이 값을 리터럴로 다시 적지 않고 필터 훅으로만 조정합니다. | | - result_cap: 총 건수를 정확히 세는 상한. 이 값을 넘는 매칭은 "이상" 으로만 보고합니다. | 페이지 이동은 상한과 무관하게 끝까지 열려 있고, 계산이 불가능해지는 것은 | 마지막 페이지 번호 하나뿐입니다. | - max_page: 직접 요청할 수 있는 페이지 번호 상한 (남용 차단용). | | 둘 다 0 이면 무제한입니다. */ 'pagination' => [ 'result_cap' => 10000, 'max_page' => 1000, ], /* |-------------------------------------------------------------------------- | 부트스트랩 리소스 정적 게시 (bake) |-------------------------------------------------------------------------- | 초기 부트스트랩 리소스(다국어 병합·컴포넌트 정의·라우트·확장 번들·템플릿 | dist 에셋)를 캐시 버전 디렉토리(`public/build/ext/{v}/`)에 실파일로 게시해 | 웹서버가 rewrite 전에 직접 서빙하는 fast path 의 스위치입니다. | | 끄면(false) 게시가 중단되고 blade 가 정적 URL 을 방출하지 않아 전면 API | 폴백(종전 동작)으로 돌아갑니다. 이미 게시된 파일은 참조되지 않은 채 남습니다. */ 'static_cache' => [ 'enabled' => env('G7_STATIC_CACHE', true), ], /* |-------------------------------------------------------------------------- | 아웃바운드 프록시 연결 테스트 |-------------------------------------------------------------------------- | 운영자가 환경설정에 입력한 프록시가 실제로 동작하는지, 그리고 그 프록시를 거쳐 | 나갔을 때 상대편에 어떤 IP 로 보이는지 확인하는 데 쓰는 조회 대상입니다. | | 출발지 IP 는 운영자가 결제사·외부 서비스에 등록해야 하는 값이라, 프록시를 켠 상태의 | 실제 값을 알려주는 것이 이 테스트의 목적입니다. 목록은 순차 시도하며 먼저 유효한 | IP 를 돌려준 곳에서 멈춥니다. 폐쇄망 등 외부 조회가 불가능한 환경에서는 목록을 | 비워 두면 도달성만 확인하고 IP 는 보고하지 않습니다. */ 'outbound_proxy' => [ 'egress_lookup_urls' => [ 'https://api.ipify.org', 'https://ifconfig.me/ip', 'https://icanhazip.com', ], 'test_timeout_seconds' => 10, ], /* |-------------------------------------------------------------------------- | 검색 — DBMS 별 부분일치 연산자 |-------------------------------------------------------------------------- | 전문검색을 제공하지 않는 DBMS 로 설치된 사이트에서는 부분일치(LIKE)가 정상 검색 | 경로입니다. 그런데 "대소문자를 구분하지 않는 부분일치" 를 어떤 연산자로 쓰는지는 | DBMS 마다 다릅니다 — 대부분 기본 비교가 구분하지 않아 `like` 로 충분하지만, | 그렇지 않은 DBMS 는 전용 연산자를 씁니다. | | 코어 코드에 드라이버명을 적지 않기 위해 이 표에 선언합니다. 새 DBMS 를 공식 지원할 | 때는 여기에 한 줄을 더하면 되고, 확장은 `core.search.like_operators` 필터 훅으로 | 조정합니다. 표에 없는 드라이버는 `like_operator_default` 를 씁니다. | | 키는 `DB::getDriverName()` 이 돌려주는 값입니다. */ 'search' => [ 'like_operators' => [ 'pgsql' => 'ilike', ], 'like_operator_default' => 'like', ], /* |-------------------------------------------------------------------------- | 스토리지 — 공개 자산 직접 URL 서빙 디스크 |-------------------------------------------------------------------------- | 완전 공개 자산(상품/카테고리/리뷰/에디터 이미지)의 직접 URL(CDN) 서빙에 쓸 | 디스크입니다. 빈 문자열이면 미설정(기존 PHP 스트리밍 유지)이며, 값은 관리자 | 환경설정(drivers.public_asset_disk)에서 SettingsServiceProvider 가 주입합니다. | 확장은 개별 설정으로 이 전역값을 오버라이드할 수 있습니다. */ 'storage' => [ 'public_asset_disk' => '', ], /* |-------------------------------------------------------------------------- | 코어 권한 정의 |-------------------------------------------------------------------------- | RolePermissionSeeder 및 CoreUpdateService::syncCoreRolesAndPermissions()에서 사용 | 새 권한 추가 시 이 배열에 추가하면 설치/업데이트 모두 반영됩니다. | | 구조: 모듈(1레벨) → 카테고리(2레벨) → 개별 권한(3레벨) */ 'permissions' => [ // 1레벨: 코어 모듈 'module' => [ 'identifier' => 'core', 'name' => ['ko' => '코어', 'en' => 'Core'], 'description' => ['ko' => '코어 시스템 권한', 'en' => 'Core system permissions'], 'order' => 1, ], // 2레벨: 카테고리들 + 3레벨: 개별 권한 'categories' => [ [ 'identifier' => 'core.users', 'name' => ['ko' => '사용자 관리', 'en' => 'User Management'], 'description' => ['ko' => '사용자 관리 권한', 'en' => 'User management permissions'], 'category' => 'users', 'order' => 1, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.users.read', 'type' => 'admin', 'name' => ['ko' => '사용자 조회', 'en' => 'View Users'], 'description' => ['ko' => '사용자 목록 및 상세 정보를 조회할 수 있습니다.', 'en' => 'Can view user list and details.'], 'order' => 1, 'resource_route_key' => 'user', 'owner_key' => 'id'], ['identifier' => 'core.users.create', 'type' => 'admin', 'name' => ['ko' => '사용자 생성', 'en' => 'Create Users'], 'description' => ['ko' => '새로운 사용자를 생성할 수 있습니다.', 'en' => 'Can create new users.'], 'order' => 2], ['identifier' => 'core.users.update', 'type' => 'admin', 'name' => ['ko' => '사용자 수정', 'en' => 'Update Users'], 'description' => ['ko' => '사용자 정보를 수정할 수 있습니다.', 'en' => 'Can update user information.'], 'order' => 3, 'resource_route_key' => 'user', 'owner_key' => 'id'], ['identifier' => 'core.users.delete', 'type' => 'admin', 'name' => ['ko' => '사용자 삭제', 'en' => 'Delete Users'], 'description' => ['ko' => '사용자를 삭제할 수 있습니다.', 'en' => 'Can delete users.'], 'order' => 4, 'resource_route_key' => 'user', 'owner_key' => 'id'], ], ], [ 'identifier' => 'core.menus', 'name' => ['ko' => '메뉴 관리', 'en' => 'Menu Management'], 'description' => ['ko' => '메뉴 관리 권한', 'en' => 'Menu management permissions'], 'category' => 'menus', 'order' => 2, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.menus.read', 'type' => 'admin', 'name' => ['ko' => '메뉴 조회', 'en' => 'View Menus'], 'description' => ['ko' => '메뉴 목록을 조회할 수 있습니다.', 'en' => 'Can view menu list.'], 'order' => 1, 'resource_route_key' => 'menu', 'owner_key' => 'created_by'], ['identifier' => 'core.menus.create', 'type' => 'admin', 'name' => ['ko' => '메뉴 생성', 'en' => 'Create Menus'], 'description' => ['ko' => '새로운 메뉴를 생성할 수 있습니다.', 'en' => 'Can create new menus.'], 'order' => 2], ['identifier' => 'core.menus.update', 'type' => 'admin', 'name' => ['ko' => '메뉴 수정', 'en' => 'Update Menus'], 'description' => ['ko' => '메뉴 정보를 수정할 수 있습니다.', 'en' => 'Can update menu information.'], 'order' => 3, 'resource_route_key' => 'menu', 'owner_key' => 'created_by'], ['identifier' => 'core.menus.delete', 'type' => 'admin', 'name' => ['ko' => '메뉴 삭제', 'en' => 'Delete Menus'], 'description' => ['ko' => '메뉴를 삭제할 수 있습니다.', 'en' => 'Can delete menus.'], 'order' => 4, 'resource_route_key' => 'menu', 'owner_key' => 'created_by'], ], ], [ 'identifier' => 'core.modules', 'name' => ['ko' => '모듈 관리', 'en' => 'Module Management'], 'description' => ['ko' => '모듈 관리 권한', 'en' => 'Module management permissions'], 'category' => 'modules', 'order' => 3, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.modules.read', 'type' => 'admin', 'name' => ['ko' => '모듈 조회', 'en' => 'View Modules'], 'description' => ['ko' => '모듈 목록을 조회할 수 있습니다.', 'en' => 'Can view module list.'], 'order' => 1], ['identifier' => 'core.modules.install', 'type' => 'admin', 'name' => ['ko' => '모듈 설치', 'en' => 'Install Modules'], 'description' => ['ko' => '새로운 모듈을 설치할 수 있습니다.', 'en' => 'Can install new modules.'], 'order' => 2], ['identifier' => 'core.modules.activate', 'type' => 'admin', 'name' => ['ko' => '모듈 활성화', 'en' => 'Activate Modules'], 'description' => ['ko' => '모듈을 활성화/비활성화할 수 있습니다.', 'en' => 'Can activate/deactivate modules.'], 'order' => 3], ['identifier' => 'core.modules.uninstall', 'type' => 'admin', 'name' => ['ko' => '모듈 삭제', 'en' => 'Uninstall Modules'], 'description' => ['ko' => '모듈을 삭제할 수 있습니다.', 'en' => 'Can uninstall modules.'], 'order' => 4], ], ], [ 'identifier' => 'core.plugins', 'name' => ['ko' => '플러그인 관리', 'en' => 'Plugin Management'], 'description' => ['ko' => '플러그인 관리 권한', 'en' => 'Plugin management permissions'], 'category' => 'plugins', 'order' => 4, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.plugins.read', 'type' => 'admin', 'name' => ['ko' => '플러그인 조회', 'en' => 'View Plugins'], 'description' => ['ko' => '플러그인 목록을 조회할 수 있습니다.', 'en' => 'Can view plugin list.'], 'order' => 1], ['identifier' => 'core.plugins.install', 'type' => 'admin', 'name' => ['ko' => '플러그인 설치', 'en' => 'Install Plugins'], 'description' => ['ko' => '새로운 플러그인을 설치할 수 있습니다.', 'en' => 'Can install new plugins.'], 'order' => 2], ['identifier' => 'core.plugins.activate', 'type' => 'admin', 'name' => ['ko' => '플러그인 활성화', 'en' => 'Activate Plugins'], 'description' => ['ko' => '플러그인을 활성화/비활성화할 수 있습니다.', 'en' => 'Can activate/deactivate plugins.'], 'order' => 3], ['identifier' => 'core.plugins.update', 'type' => 'admin', 'name' => ['ko' => '플러그인 설정', 'en' => 'Configure Plugins'], 'description' => ['ko' => '플러그인 환경설정을 수정할 수 있습니다.', 'en' => 'Can update plugin settings.'], 'order' => 4], ['identifier' => 'core.plugins.uninstall', 'type' => 'admin', 'name' => ['ko' => '플러그인 삭제', 'en' => 'Uninstall Plugins'], 'description' => ['ko' => '플러그인을 삭제할 수 있습니다.', 'en' => 'Can uninstall plugins.'], 'order' => 5], ], ], [ 'identifier' => 'core.templates', 'name' => ['ko' => '템플릿 관리', 'en' => 'Template Management'], 'description' => ['ko' => '템플릿 관리 권한', 'en' => 'Template management permissions'], 'category' => 'templates', 'order' => 5, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.templates.read', 'type' => 'admin', 'name' => ['ko' => '템플릿 조회', 'en' => 'View Templates'], 'description' => ['ko' => '템플릿 목록을 조회할 수 있습니다.', 'en' => 'Can view template list.'], 'order' => 1], ['identifier' => 'core.templates.install', 'type' => 'admin', 'name' => ['ko' => '템플릿 설치', 'en' => 'Install Templates'], 'description' => ['ko' => '새로운 템플릿을 설치할 수 있습니다.', 'en' => 'Can install new templates.'], 'order' => 2], ['identifier' => 'core.templates.activate', 'type' => 'admin', 'name' => ['ko' => '템플릿 활성화', 'en' => 'Activate Templates'], 'description' => ['ko' => '템플릿을 활성화/비활성화할 수 있습니다.', 'en' => 'Can activate/deactivate templates.'], 'order' => 3], ['identifier' => 'core.templates.uninstall', 'type' => 'admin', 'name' => ['ko' => '템플릿 삭제', 'en' => 'Uninstall Templates'], 'description' => ['ko' => '템플릿을 삭제할 수 있습니다.', 'en' => 'Can uninstall templates.'], 'order' => 4], ['identifier' => 'core.templates.layouts.edit', 'type' => 'admin', 'name' => ['ko' => '레이아웃 편집', 'en' => 'Edit Layouts'], 'description' => ['ko' => '템플릿 레이아웃을 편집할 수 있습니다.', 'en' => 'Can edit template layouts.'], 'order' => 5], ], ], [ 'identifier' => 'core.extensions', 'name' => ['ko' => '확장 공통', 'en' => 'Extension Common'], 'description' => ['ko' => '모듈·플러그인·템플릿에 공통으로 적용되는 권한', 'en' => 'Permissions that apply across modules, plugins and templates'], 'category' => 'extensions', 'order' => 5.5, 'type' => 'admin', 'permissions' => [ // 확장 타입을 가리지 않는 단일 권한이다. 타입별로 쪼개면 운영자가 셋을 모두 // 부여해야 하고, "모듈 CSS 는 되는데 템플릿 CSS 는 안 되는" 상태가 실질적 // 의미 없이 생긴다. 레이아웃 편집 권한과는 분리한다 — 여기서 올린 스크립트는 // 그 레이아웃 한 장이 아니라 사이트 전 화면에서 실행되므로, 레이아웃을 고칠 // 수 있다는 것이 곧 그 권한이 될 수 없다. ['identifier' => 'core.extensions.custom_assets.manage', 'type' => 'admin', 'name' => ['ko' => '커스텀 자산 관리', 'en' => 'Manage Custom Assets'], 'description' => ['ko' => '모듈·플러그인·템플릿에 운영자 CSS·JS·폰트·이미지를 추가하거나 수정할 수 있습니다. 추가한 스크립트는 사이트 전체에서 실행되므로 레이아웃 편집과 별도로 부여합니다.', 'en' => 'Can add or edit operator CSS/JS/fonts/images on modules, plugins and templates. Added scripts run across the whole site, so this is granted separately from layout editing.'], 'order' => 1], ], ], [ 'identifier' => 'core.permissions', 'name' => ['ko' => '권한 관리', 'en' => 'Permission Management'], 'description' => ['ko' => '역할 및 권한 관리 권한', 'en' => 'Role and permission management permissions'], 'category' => 'permissions', 'order' => 6, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.permissions.read', 'type' => 'admin', 'name' => ['ko' => '권한 조회', 'en' => 'View Permissions'], 'description' => ['ko' => '역할 및 권한 목록을 조회할 수 있습니다.', 'en' => 'Can view roles and permissions.'], 'order' => 1], ['identifier' => 'core.permissions.create', 'type' => 'admin', 'name' => ['ko' => '역할 생성', 'en' => 'Create Roles'], 'description' => ['ko' => '새로운 역할을 생성할 수 있습니다.', 'en' => 'Can create new roles.'], 'order' => 2], ['identifier' => 'core.permissions.update', 'type' => 'admin', 'name' => ['ko' => '역할 수정', 'en' => 'Update Roles'], 'description' => ['ko' => '역할 정보와 권한을 수정할 수 있습니다.', 'en' => 'Can update role information and permissions.'], 'order' => 3], ['identifier' => 'core.permissions.delete', 'type' => 'admin', 'name' => ['ko' => '역할 삭제', 'en' => 'Delete Roles'], 'description' => ['ko' => '역할을 삭제할 수 있습니다.', 'en' => 'Can delete roles.'], 'order' => 4], ], ], [ 'identifier' => 'core.notification-logs', 'name' => ['ko' => '알림 발송 이력', 'en' => 'Notification Logs'], 'description' => ['ko' => '알림 발송 이력 관리 권한', 'en' => 'Notification log management permissions'], 'category' => 'notification-logs', 'order' => 7, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.notification-logs.read', 'type' => 'admin', 'name' => ['ko' => '발송 이력 조회', 'en' => 'View Notification Logs'], 'description' => ['ko' => '알림 발송 이력을 조회할 수 있습니다.', 'en' => 'Can view notification logs.'], 'order' => 1], ['identifier' => 'core.notification-logs.delete', 'type' => 'admin', 'name' => ['ko' => '발송 이력 삭제', 'en' => 'Delete Notification Logs'], 'description' => ['ko' => '알림 발송 이력을 삭제할 수 있습니다.', 'en' => 'Can delete notification logs.'], 'order' => 2], ], ], [ 'identifier' => 'core.notifications', 'name' => ['ko' => '알림 (관리자)', 'en' => 'Notifications (Admin)'], 'description' => ['ko' => '관리자용 알림 관리 권한 (관리자 화면에서 사용)', 'en' => 'Admin notification management permissions (used in admin UI)'], 'category' => 'notifications', 'order' => 7.5, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.notifications.read', 'type' => 'admin', 'name' => ['ko' => '알림 조회', 'en' => 'View Notifications'], 'description' => ['ko' => '알림 목록 및 읽지 않은 수를 조회할 수 있습니다.', 'en' => 'Can view notification list and unread count.'], 'order' => 1], ['identifier' => 'core.notifications.update', 'type' => 'admin', 'name' => ['ko' => '알림 읽음 처리', 'en' => 'Mark Notifications Read'], 'description' => ['ko' => '알림을 읽음 처리할 수 있습니다.', 'en' => 'Can mark notifications as read.'], 'order' => 2], ['identifier' => 'core.notifications.delete', 'type' => 'admin', 'name' => ['ko' => '알림 삭제', 'en' => 'Delete Notifications'], 'description' => ['ko' => '알림을 삭제할 수 있습니다.', 'en' => 'Can delete notifications.'], 'order' => 3], ], ], [ 'identifier' => 'core.user-notifications', 'name' => ['ko' => '알림 (사용자)', 'en' => 'Notifications (User)'], 'description' => ['ko' => '사용자용 알림 권한 (사용자 화면에서 본인 알림 관리)', 'en' => 'User notification permissions (managing own notifications in user UI)'], 'category' => 'user-notifications', 'order' => 7.6, 'type' => 'user', 'permissions' => [ ['identifier' => 'core.user-notifications.read', 'type' => 'user', 'name' => ['ko' => '알림 조회', 'en' => 'View Notifications'], 'description' => ['ko' => '본인의 알림 목록 및 읽지 않은 수를 조회할 수 있습니다.', 'en' => 'Can view own notification list and unread count.'], 'order' => 1], ['identifier' => 'core.user-notifications.update', 'type' => 'user', 'name' => ['ko' => '알림 읽음 처리', 'en' => 'Mark Notifications Read'], 'description' => ['ko' => '본인의 알림을 읽음 처리할 수 있습니다.', 'en' => 'Can mark own notifications as read.'], 'order' => 2], ['identifier' => 'core.user-notifications.delete', 'type' => 'user', 'name' => ['ko' => '알림 삭제', 'en' => 'Delete Notifications'], 'description' => ['ko' => '본인의 알림을 삭제할 수 있습니다.', 'en' => 'Can delete own notifications.'], 'order' => 3], ], ], [ 'identifier' => 'core.identity', 'name' => ['ko' => '본인인증 (사용자)', 'en' => 'Identity Verification (User)'], 'description' => ['ko' => '로그인 사용자의 본인인증 challenge 요청/검증/취소 권한', 'en' => 'Permissions for authenticated users to request/verify/cancel IDV challenges'], 'category' => 'identity', 'order' => 7.7, 'type' => 'user', 'permissions' => [ ['identifier' => 'core.identity.request', 'type' => 'user', 'name' => ['ko' => 'IDV 요청', 'en' => 'Request IDV Challenge'], 'description' => ['ko' => '본인인증 challenge 를 요청할 수 있습니다.', 'en' => 'Can request identity verification challenges.'], 'order' => 1], ['identifier' => 'core.identity.verify', 'type' => 'user', 'name' => ['ko' => 'IDV 검증', 'en' => 'Verify IDV Challenge'], 'description' => ['ko' => '본인의 본인인증 challenge 를 검증할 수 있습니다.', 'en' => 'Can verify own identity verification challenges.'], 'order' => 2, 'resource_route_key' => 'challenge', 'owner_key' => 'user_id'], ['identifier' => 'core.identity.cancel', 'type' => 'user', 'name' => ['ko' => 'IDV 취소', 'en' => 'Cancel IDV Challenge'], 'description' => ['ko' => '본인의 본인인증 challenge 를 취소할 수 있습니다.', 'en' => 'Can cancel own identity verification challenges.'], 'order' => 3, 'resource_route_key' => 'challenge', 'owner_key' => 'user_id'], ], ], [ 'identifier' => 'core.admin.identity', 'name' => ['ko' => '본인인증 관리 (관리자)', 'en' => 'Identity Verification Management (Admin)'], 'description' => ['ko' => '관리자용 IDV 프로바이더/정책/로그 관리 권한', 'en' => 'Admin permissions for IDV providers, policies, and logs'], 'category' => 'identity', 'order' => 7.8, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.admin.identity.providers.read', 'type' => 'admin', 'name' => ['ko' => '프로바이더 설정 조회', 'en' => 'View IDV Providers'], 'description' => ['ko' => '본인인증 프로바이더 설정을 조회할 수 있습니다.', 'en' => 'Can view identity verification providers.'], 'order' => 1], ['identifier' => 'core.admin.identity.providers.update', 'type' => 'admin', 'name' => ['ko' => '프로바이더 설정 수정', 'en' => 'Update IDV Providers'], 'description' => ['ko' => '본인인증 프로바이더 설정을 수정할 수 있습니다.', 'en' => 'Can update identity verification providers.'], 'order' => 2], ['identifier' => 'core.admin.identity.policies.read', 'type' => 'admin', 'name' => ['ko' => '정책 조회', 'en' => 'View IDV Policies'], 'description' => ['ko' => '본인인증 정책(라우트/훅별)을 조회할 수 있습니다.', 'en' => 'Can view identity verification policies by route/hook.'], 'order' => 3], ['identifier' => 'core.admin.identity.policies.update', 'type' => 'admin', 'name' => ['ko' => '정책 수정', 'en' => 'Update IDV Policies'], 'description' => ['ko' => '본인인증 정책(라우트/훅별)을 CRUD 할 수 있습니다.', 'en' => 'Can CRUD identity verification policies by route/hook.'], 'order' => 4], ['identifier' => 'core.admin.identity.logs.read', 'type' => 'admin', 'name' => ['ko' => '로그 열람', 'en' => 'View IDV Logs'], 'description' => ['ko' => '본인인증 이력을 조회할 수 있습니다.', 'en' => 'Can view identity verification logs.'], 'order' => 5], ['identifier' => 'core.admin.identity.logs.purge', 'type' => 'admin', 'name' => ['ko' => '로그 파기', 'en' => 'Purge IDV Logs'], 'description' => ['ko' => '본인인증 이력을 파기(보관주기 외)할 수 있습니다.', 'en' => 'Can purge identity verification logs (retention-based).'], 'order' => 6], ['identifier' => 'core.admin.identity.messages.read', 'type' => 'admin', 'name' => ['ko' => '메시지 템플릿 조회', 'en' => 'View IDV Message Templates'], 'description' => ['ko' => '본인인증 메시지 정의/템플릿을 조회할 수 있습니다.', 'en' => 'Can view identity verification message definitions and templates.'], 'order' => 7], ['identifier' => 'core.admin.identity.messages.update', 'type' => 'admin', 'name' => ['ko' => '메시지 템플릿 수정', 'en' => 'Update IDV Message Templates'], 'description' => ['ko' => '본인인증 메시지 정의/템플릿을 수정할 수 있습니다.', 'en' => 'Can update identity verification message definitions and templates.'], 'order' => 8], ], ], [ 'identifier' => 'core.settings', 'name' => ['ko' => '환경설정', 'en' => 'Settings'], 'description' => ['ko' => '시스템 환경설정 권한', 'en' => 'System settings permissions'], 'category' => 'settings', 'order' => 8, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.settings.read', 'type' => 'admin', 'name' => ['ko' => '설정 조회', 'en' => 'View Settings'], 'description' => ['ko' => '시스템 설정을 조회할 수 있습니다.', 'en' => 'Can view system settings.'], 'order' => 1], ['identifier' => 'core.settings.update', 'type' => 'admin', 'name' => ['ko' => '설정 수정', 'en' => 'Update Settings'], 'description' => ['ko' => '시스템 설정을 수정할 수 있습니다.', 'en' => 'Can update system settings.'], 'order' => 2], ], ], [ 'identifier' => 'core.dashboard', 'name' => ['ko' => '대시보드', 'en' => 'Dashboard'], 'description' => ['ko' => '대시보드 접근 권한', 'en' => 'Dashboard access permissions'], 'category' => 'dashboard', 'order' => 9, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.dashboard.read', 'type' => 'admin', 'name' => ['ko' => '대시보드 조회', 'en' => 'View Dashboard'], 'description' => ['ko' => '대시보드 통계 및 정보를 조회할 수 있습니다.', 'en' => 'Can view dashboard statistics and information.'], 'order' => 1], ['identifier' => 'core.dashboard.system-status', 'type' => 'admin', 'name' => ['ko' => '시스템 상태', 'en' => 'System Status'], 'description' => ['ko' => '시스템 상태 정보를 조회할 수 있습니다.', 'en' => 'Can view system status information.'], 'order' => 2], ['identifier' => 'core.dashboard.resources', 'type' => 'admin', 'name' => ['ko' => '시스템 리소스', 'en' => 'System Resources'], 'description' => ['ko' => 'CPU, 메모리, 디스크 사용량을 조회할 수 있습니다.', 'en' => 'Can view CPU, memory, and disk usage.'], 'order' => 3], ['identifier' => 'core.dashboard.activities', 'type' => 'admin', 'name' => ['ko' => '최근 활동', 'en' => 'Recent Activities'], 'description' => ['ko' => '최근 활동 이력을 조회할 수 있습니다.', 'en' => 'Can view recent activity history.'], 'order' => 4, 'resource_route_key' => 'activityLog', 'owner_key' => 'user_id'], ['identifier' => 'core.dashboard.alerts', 'type' => 'admin', 'name' => ['ko' => '시스템 알림', 'en' => 'System Alerts'], 'description' => ['ko' => '시스템 알림을 조회할 수 있습니다.', 'en' => 'Can view system alerts.'], 'order' => 5], ], ], [ 'identifier' => 'core.activities', 'name' => ['ko' => '활동 로그', 'en' => 'Activity Logs'], 'description' => ['ko' => '활동 로그 조회 권한', 'en' => 'Activity log access permissions'], 'category' => 'activities', 'order' => 10, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.activities.read', 'type' => 'admin', 'name' => ['ko' => '활동 로그 조회', 'en' => 'View Activity Logs'], 'description' => ['ko' => '활동 로그를 조회할 수 있습니다.', 'en' => 'Can view activity logs.'], 'order' => 1, 'resource_route_key' => 'activityLog', 'owner_key' => 'user_id'], ['identifier' => 'core.activities.delete', 'type' => 'admin', 'name' => ['ko' => '활동 로그 삭제', 'en' => 'Delete Activity Logs'], 'description' => ['ko' => '활동 로그를 삭제할 수 있습니다.', 'en' => 'Can delete activity logs.'], 'order' => 2], ], ], [ 'identifier' => 'core.attachments', 'name' => ['ko' => '첨부파일 관리', 'en' => 'Attachment Management'], 'description' => ['ko' => '첨부파일 관리 권한', 'en' => 'Attachment management permissions'], 'category' => 'attachments', 'order' => 11, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.attachments.create', 'type' => 'admin', 'name' => ['ko' => '첨부파일 업로드', 'en' => 'Upload Attachments'], 'description' => ['ko' => '첨부파일을 업로드할 수 있습니다.', 'en' => 'Can upload attachments.'], 'order' => 1], ['identifier' => 'core.attachments.update', 'type' => 'admin', 'name' => ['ko' => '첨부파일 수정', 'en' => 'Update Attachments'], 'description' => ['ko' => '첨부파일 정보 및 순서를 수정할 수 있습니다.', 'en' => 'Can update attachment information and order.'], 'order' => 2, 'resource_route_key' => 'attachment', 'owner_key' => 'created_by'], ['identifier' => 'core.attachments.delete', 'type' => 'admin', 'name' => ['ko' => '첨부파일 삭제', 'en' => 'Delete Attachments'], 'description' => ['ko' => '첨부파일을 삭제할 수 있습니다.', 'en' => 'Can delete attachments.'], 'order' => 3, 'resource_route_key' => 'attachment', 'owner_key' => 'created_by'], ], ], [ 'identifier' => 'core.schedules', 'name' => ['ko' => '스케줄 관리', 'en' => 'Schedule Management'], 'description' => ['ko' => '스케줄 작업 관리 권한', 'en' => 'Schedule task management permissions'], 'category' => 'schedules', 'order' => 12, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.schedules.read', 'type' => 'admin', 'name' => ['ko' => '스케줄 조회', 'en' => 'View Schedules'], 'description' => ['ko' => '스케줄 목록 및 상세 정보를 조회할 수 있습니다.', 'en' => 'Can view schedule list and details.'], 'order' => 1], ['identifier' => 'core.schedules.create', 'type' => 'admin', 'name' => ['ko' => '스케줄 생성', 'en' => 'Create Schedules'], 'description' => ['ko' => '새로운 스케줄을 생성할 수 있습니다.', 'en' => 'Can create new schedules.'], 'order' => 2], ['identifier' => 'core.schedules.update', 'type' => 'admin', 'name' => ['ko' => '스케줄 수정', 'en' => 'Update Schedules'], 'description' => ['ko' => '스케줄 정보를 수정할 수 있습니다.', 'en' => 'Can update schedule information.'], 'order' => 3], ['identifier' => 'core.schedules.delete', 'type' => 'admin', 'name' => ['ko' => '스케줄 삭제', 'en' => 'Delete Schedules'], 'description' => ['ko' => '스케줄을 삭제할 수 있습니다.', 'en' => 'Can delete schedules.'], 'order' => 4], ['identifier' => 'core.schedules.run', 'type' => 'admin', 'name' => ['ko' => '스케줄 실행', 'en' => 'Run Schedules'], 'description' => ['ko' => '스케줄을 수동으로 실행할 수 있습니다.', 'en' => 'Can manually run schedules.'], 'order' => 5], ], ], [ 'identifier' => 'core.language_packs', 'name' => ['ko' => '언어팩 관리', 'en' => 'Language Pack Management'], 'description' => ['ko' => '언어팩 설치/제거/활성화 권한', 'en' => 'Language pack install/uninstall/activation permissions'], 'category' => 'language_packs', 'order' => 13, 'type' => 'admin', 'permissions' => [ ['identifier' => 'core.language_packs.read', 'type' => 'admin', 'name' => ['ko' => '언어팩 조회', 'en' => 'View Language Packs'], 'description' => ['ko' => '설치된 언어팩 목록 및 상세 정보를 조회할 수 있습니다.', 'en' => 'Can view installed language pack list and details.'], 'order' => 1], ['identifier' => 'core.language_packs.install', 'type' => 'admin', 'name' => ['ko' => '언어팩 설치', 'en' => 'Install Language Packs'], 'description' => ['ko' => 'ZIP/GitHub/URL 로 언어팩을 설치할 수 있습니다.', 'en' => 'Can install language packs from ZIP/GitHub/URL.'], 'order' => 2], ['identifier' => 'core.language_packs.manage', 'type' => 'admin', 'name' => ['ko' => '언어팩 관리', 'en' => 'Manage Language Packs'], 'description' => ['ko' => '언어팩을 활성화/비활성화/제거할 수 있습니다.', 'en' => 'Can activate/deactivate/uninstall language packs.'], 'order' => 3], ['identifier' => 'core.language_packs.update', 'type' => 'admin', 'name' => ['ko' => '언어팩 업데이트', 'en' => 'Update Language Packs'], 'description' => ['ko' => '설치된 언어팩의 업데이트를 확인하고 실행할 수 있습니다.', 'en' => 'Can check and apply updates for installed language packs.'], 'order' => 4], ], ], ], ], /* |-------------------------------------------------------------------------- | 코어 역할 정의 |-------------------------------------------------------------------------- | RolePermissionSeeder 및 CoreUpdateService::syncCoreRolesAndPermissions()에서 사용 */ 'roles' => [ [ 'identifier' => 'admin', 'name' => ['ko' => '관리자', 'en' => 'Administrator'], 'description' => ['ko' => '시스템의 모든 기능에 접근할 수 있는 최고 관리자입니다.', 'en' => 'Super administrator with access to all system features.'], 'attributes' => ['is_active' => true], 'permissions' => 'all_leaf', // 모든 리프 권한 할당 ], [ 'identifier' => 'manager', 'name' => ['ko' => '매니저', 'en' => 'Manager'], 'description' => ['ko' => '콘텐츠 및 사용자 관리 권한을 가진 관리자입니다.', 'en' => 'Manager with content and user management permissions.'], 'attributes' => ['is_active' => true], 'permissions' => [ 'core.users.read', 'core.users.create', 'core.users.update', 'core.menus.read', 'core.menus.create', 'core.menus.update', 'core.dashboard.read', 'core.dashboard.system-status', 'core.dashboard.activities', 'core.activities.read', 'core.attachments.create', 'core.attachments.update', 'core.attachments.delete', 'core.notification-logs.read', ], // 권한별 스코프 지정 (self: 본인 소유만, role: 같은 역할 범위, 미지정: 전체) 'permission_scopes' => [ 'core.users.read' => 'self', 'core.users.update' => 'self', 'core.activities.read' => 'self', 'core.attachments.update' => 'self', 'core.attachments.delete' => 'self', 'core.notification-logs.read' => 'self', ], ], [ 'identifier' => 'user', 'name' => ['ko' => '일반 사용자', 'en' => 'User'], 'description' => ['ko' => '기본 사용자 역할입니다.', 'en' => 'Default user role.'], 'attributes' => ['is_active' => true], 'permissions' => [ 'core.user-notifications.read', 'core.user-notifications.update', 'core.user-notifications.delete', 'core.identity.request', 'core.identity.verify', 'core.identity.cancel', ], // verify/cancel 은 본인 challenge(user_id 일치) 만 — PermissionMiddleware 의 scope=self 가드가 자동 검증 'permission_scopes' => [ 'core.identity.verify' => 'self', 'core.identity.cancel' => 'self', ], ], [ 'identifier' => 'guest', 'name' => ['ko' => '비회원', 'en' => 'Guest'], 'description' => [ 'ko' => '인증되지 않은 사용자 역할입니다. 관리자가 권한을 부여할 수 있습니다.', 'en' => 'Unauthenticated user role. Permissions can be granted by administrators.', ], 'attributes' => ['is_active' => true], // 비로그인 가입(Mode B) · 비밀번호 재설정 등 IDV 진입에 필요 — PermissionMiddleware 가 비인증 시 scope 검사를 자동 스킵하므로 owner 가드는 throttle + UUID 추정 어려움에 의존 'permissions' => [ 'core.identity.request', 'core.identity.verify', 'core.identity.cancel', ], ], ], /* |-------------------------------------------------------------------------- | 코어 메뉴 정의 |-------------------------------------------------------------------------- | CoreAdminMenuSeeder 및 CoreUpdateService::syncCoreMenus()에서 사용 */ 'menus' => [ [ 'slug' => 'admin-dashboard', 'name' => ['ko' => '대시보드', 'en' => 'Dashboard'], 'url' => '/admin/dashboard', 'icon' => 'fas fa-tachometer-alt', 'parent_id' => null, 'order' => 1, 'is_active' => true, ], [ 'slug' => 'admin-settings', 'name' => ['ko' => '환경설정', 'en' => 'Settings'], 'url' => '/admin/settings', 'icon' => 'fas fa-cog', 'parent_id' => null, 'order' => 2, 'is_active' => true, ], [ 'slug' => 'admin-notification-logs', 'name' => ['ko' => '알림 발송 이력', 'en' => 'Notification Logs'], 'url' => '/admin/notification-logs', 'icon' => 'fas fa-bell', 'parent_id' => null, 'order' => 3, 'is_active' => true, ], [ 'slug' => 'admin-identity-logs', 'name' => ['ko' => '본인인증 이력', 'en' => 'Identity Logs'], 'url' => '/admin/identity/logs', 'icon' => 'fas fa-clipboard-check', 'parent_id' => null, 'order' => 4, 'is_active' => true, ], [ 'slug' => 'admin-activity-logs', 'name' => ['ko' => '활동 로그', 'en' => 'Activity Logs'], 'url' => '/admin/activity-logs', 'icon' => 'fas fa-history', 'parent_id' => null, 'order' => 5, 'is_active' => true, ], [ 'slug' => 'admin-menus', 'name' => ['ko' => '메뉴 관리', 'en' => 'Menu Management'], 'url' => '/admin/menus', 'icon' => 'fas fa-bars', 'parent_id' => null, 'order' => 6, 'is_active' => true, ], [ 'slug' => 'admin-users', 'name' => ['ko' => '사용자 관리', 'en' => 'User Management'], 'url' => '/admin/users', 'icon' => 'fas fa-users', 'parent_id' => null, 'order' => 7, 'is_active' => true, ], [ 'slug' => 'admin-roles', 'name' => ['ko' => '권한 관리', 'en' => 'Permission Management'], 'url' => '/admin/roles', 'icon' => 'fas fa-lock', 'parent_id' => null, 'order' => 8, 'is_active' => true, ], [ 'slug' => 'admin-modules', 'name' => ['ko' => '모듈 관리', 'en' => 'Module Management'], 'url' => '/admin/modules', 'icon' => 'fas fa-cube', 'parent_id' => null, 'order' => 9, 'is_active' => true, ], [ 'slug' => 'admin-plugins', 'name' => ['ko' => '플러그인 관리', 'en' => 'Plugin Management'], 'url' => '/admin/plugins', 'icon' => 'fas fa-puzzle-piece', 'parent_id' => null, 'order' => 10, 'is_active' => true, ], [ 'slug' => 'admin-templates', 'name' => ['ko' => '템플릿 관리', 'en' => 'Template Management'], 'url' => '/admin/templates', 'icon' => 'fas fa-palette', 'parent_id' => null, 'order' => 11, 'is_active' => true, ], [ 'slug' => 'admin-schedules', 'name' => ['ko' => '스케쥴 관리', 'en' => 'Schedule Management'], 'url' => '/admin/schedules', 'icon' => 'fas fa-clock', 'parent_id' => null, 'order' => 12, 'is_active' => false, ], ], /* |-------------------------------------------------------------------------- | 코어 알림 정의 |-------------------------------------------------------------------------- | NotificationDefinitionSeeder 와 NotificationTemplateService 가 SSoT 로 사용합니다. | NotificationSyncHelper 가 upsert 하며, 운영자가 관리자 UI 에서 수정한 필드는 | user_overrides JSON 에 보존되어 재시딩 시 덮어써지지 않습니다. | 모듈/플러그인 자체 알림은 각자의 AbstractModule/AbstractPlugin::getNotificationDefinitions() | 에서 선언하며 ModuleManager/PluginManager 가 자동 동기화합니다. */ 'notification_definitions' => [ 'welcome' => [ 'hook_prefix' => 'core.auth', 'name' => ['ko' => '회원가입 환영', 'en' => 'Welcome'], 'description' => ['ko' => '회원가입 완료 시 발송되는 환영 알림', 'en' => 'Welcome notification sent upon registration'], 'channels' => ['mail', 'database'], 'hooks' => ['core.auth.after_register'], 'variables' => [ ['key' => 'name', 'description' => '수신자 이름'], ['key' => 'app_name', 'description' => '사이트명'], ['key' => 'action_url', 'description' => '로그인 페이지 URL'], ['key' => 'site_url', 'description' => '사이트 URL'], ], 'templates' => [ [ 'channel' => 'mail', 'recipients' => [['type' => 'trigger_user']], 'subject' => [ 'ko' => '[{app_name}] 회원가입을 환영합니다', 'en' => '[{app_name}] Welcome to Our Service', ], 'body' => [ 'ko' => '
{app_name}에 가입해 주셔서 감사합니다.
' .'이제 모든 서비스를 이용하실 수 있습니다. 아래 버튼을 클릭하여 로그인해 주세요.
' .'| 로그인하기 |
감사합니다,
{app_name}
Thank you for joining {app_name}.
' .'You now have access to all our services. Click the button below to log in.
' .'| Log In |
Thank you,
{app_name}
비밀번호 재설정 요청을 받았습니다. 아래 버튼을 클릭하여 비밀번호를 재설정해 주세요.
' .'이 링크는 {expire_minutes}분 후 만료됩니다.
' .'| 비밀번호 재설정 |
비밀번호 재설정을 요청하지 않으셨다면, 이 이메일을 무시해 주세요.
' .'감사합니다,
{app_name}
We received a request to reset your password. Click the button below to set a new password.
' .'This link will expire in {expire_minutes} minutes.
' .'| Reset Password |
If you did not request a password reset, please ignore this email.
' .'Thank you,
{app_name}
계정의 비밀번호가 성공적으로 변경되었습니다.
' .'본인이 변경하지 않았다면, 즉시 고객 지원팀에 문의하시기 바랍니다.
' .'| 로그인하기 |
감사합니다,
{app_name}
Your account password has been successfully changed.
' .'If you did not make this change, please contact our support team immediately.
' .'| Log In |
Thank you,
{app_name}
요청하신 사이트맵 재생성이 완료되었습니다.
' .'총 {url_count}개의 URL 이 {child_count}개의 파일로 생성되었습니다.
' .'| SEO 설정 보기 |
감사합니다,
{app_name}
The sitemap regeneration you requested has completed.
' .'A total of {url_count} URLs were generated across {child_count} file(s).
' .'| View SEO Settings |
Thank you,
{app_name}
요청하신 사이트맵 재생성이 실패했습니다.
' .'오류: {error}
' .'| SEO 설정 보기 |
감사합니다,
{app_name}
The sitemap regeneration you requested has failed.
' .'Error: {error}
' .'| View SEO Settings |
Thank you,
{app_name}
안녕하세요.
' .'아래 인증 코드를 입력해 본인 확인을 완료해 주세요.
' .'{code}
' .'이 코드는 {expire_minutes}분 후 만료됩니다.
' .'본인이 요청하지 않았다면 이 메일을 무시해 주세요.
' .'감사합니다,
{app_name}
Hello.
' .'Please enter the verification code below to confirm your identity.
' .'{code}
' .'This code will expire in {expire_minutes} minutes.
' .'If you did not request this, please ignore this email.
' .'Thank you,
{app_name}
아래 인증 코드를 회원가입 화면에 입력해 주세요.
' .'{code}
' .'이 코드는 {expire_minutes}분 후 만료됩니다.
' .'본인이 가입을 시도하지 않았다면 이 메일을 무시해 주세요.
' .'감사합니다,
{app_name}
Please enter the verification code below on the signup screen.
' .'{code}
' .'This code will expire in {expire_minutes} minutes.
' .'If you did not request this, please ignore this email.
' .'Thank you,
{app_name}
비밀번호 재설정 요청을 받았습니다. 아래 버튼을 클릭하여 비밀번호를 재설정해 주세요.
' .'이 링크는 {expire_minutes}분 후 만료됩니다.
' .'| 비밀번호 재설정 |
본인이 요청하지 않았다면 이 메일을 무시해 주세요.
' .'감사합니다,
{app_name}
We received a password reset request. Click the button below to set a new password.
' .'This link will expire in {expire_minutes} minutes.
' .'| Reset Password |
If you did not request this, please ignore this email.
' .'Thank you,
{app_name}
{purpose_label} 처리를 위해 아래 인증 코드를 입력해 주세요.
' .'{code}
' .'이 코드는 {expire_minutes}분 후 만료됩니다.
' .'본인이 변경을 시도하지 않았다면 즉시 비밀번호를 변경하시기 바랍니다.
' .'감사합니다,
{app_name}
Please enter the code below to proceed with {purpose_label}.
' .'{code}
' .'This code will expire in {expire_minutes} minutes.
' .'If you did not initiate this change, please change your password immediately.
' .'Thank you,
{app_name}
{purpose_label} 진행을 위해 아래 인증 코드를 입력해 주세요.
' .'{code}
' .'이 코드는 {expire_minutes}분 후 만료됩니다.
' .'본인이 시도하지 않았다면 즉시 고객 지원팀에 문의해 주세요.
' .'감사합니다,
{app_name}
Please enter the code below to proceed with {purpose_label}.
' .'{code}
' .'This code will expire in {expire_minutes} minutes.
' .'If you did not initiate this action, please contact support immediately.
' .'Thank you,
{app_name}