php-tenant/Database/Seeders/FeatureSeeder.php

902 lines
36 KiB
PHP
Raw Normal View History

2026-01-26 21:08:59 +00:00
<?php
namespace Core\Mod\Tenant\Database\Seeders;
2026-01-26 21:08:59 +00:00
use Core\Mod\Tenant\Models\Feature;
2026-01-26 21:08:59 +00:00
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Schema;
class FeatureSeeder extends Seeder
{
public function run(): void
{
if (! Schema::hasTable('entitlement_features')) {
return;
}
$features = [
// Tier markers (boolean)
[
'code' => 'tier.apollo',
'name' => 'Apollo Tier',
'description' => 'Access to Apollo tier features',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'tier.hades',
'name' => 'Hades Tier',
'description' => 'Access to Hades tier features (developer tools)',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
// Lethean Network designations
[
'code' => 'tier.nyx',
'name' => 'Nyx Tier',
'description' => 'Demo/test account access (Lethean Network)',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
[
'code' => 'tier.stygian',
'name' => 'Stygian Tier',
'description' => 'Standard user access (Lethean Network)',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 4,
],
// Corporate Sponsors (Lethean Network)
[
'code' => 'tier.plouton',
'name' => 'Ploutōn Tier',
'description' => 'White label partner access (Lethean Network)',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'tier.hermes',
'name' => 'Hermes Tier',
'description' => 'Founding patron access - seat in Elysia (Lethean Network)',
'category' => 'tier',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
// Service access gates (deny by default)
[
'code' => 'core.srv.social',
'name' => 'SocialHost Access',
'description' => 'Access to SocialHost social media management',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'core.srv.bio',
'name' => 'BioHost Access',
'description' => 'Access to BioHost link-in-bio pages',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
[
'code' => 'core.srv.analytics',
'name' => 'AnalyticsHost Access',
'description' => 'Access to AnalyticsHost privacy-focused analytics',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
[
'code' => 'core.srv.trust',
'name' => 'TrustHost Access',
'description' => 'Access to TrustHost social proof notifications',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 4,
],
[
'code' => 'core.srv.notify',
'name' => 'NotifyHost Access',
'description' => 'Access to NotifyHost push notifications',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'core.srv.support',
'name' => 'SupportHost Access',
'description' => 'Access to SupportHost help desk',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
[
'code' => 'core.srv.web',
'name' => 'WebHost Access',
'description' => 'Access to WebHost site management',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 7,
],
[
'code' => 'core.srv.commerce',
'name' => 'Commerce Access',
'description' => 'Access to Commerce store management',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 8,
],
[
'code' => 'core.srv.hub',
'name' => 'Hub Access',
'description' => 'Access to Hub admin panel',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 0, // Internal service
],
[
'code' => 'core.srv.agentic',
'name' => 'Agentic Access',
'description' => 'Access to AI agent services',
'category' => 'service',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 9,
],
// Social features
[
'code' => 'social.accounts',
'name' => 'Social Accounts',
'description' => 'Number of connected social media accounts',
'category' => 'social',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'social.posts.scheduled',
'name' => 'Scheduled Posts',
'description' => 'Number of scheduled posts per month',
'category' => 'social',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 2,
],
[
'code' => 'social.workspaces',
'name' => 'Social Workspaces',
'description' => 'Number of social workspaces',
'category' => 'social',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
[
'code' => 'social.posts.bulk',
'name' => 'Bulk Post Upload',
'description' => 'Upload multiple posts via CSV/bulk import',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 4,
],
[
'code' => 'social.analytics',
'name' => 'Social Analytics',
'description' => 'Access to social media analytics',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'social.analytics.advanced',
'name' => 'Advanced Analytics',
'description' => 'Advanced reporting and analytics features',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
[
'code' => 'social.team',
'name' => 'Team Collaboration',
'description' => 'Multi-user team features for social management',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 7,
],
[
'code' => 'social.approval_workflow',
'name' => 'Approval Workflow',
'description' => 'Content approval workflow before posting',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 8,
],
[
'code' => 'social.white_label',
'name' => 'White Label',
'description' => 'Remove SocialHost branding',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 9,
],
[
'code' => 'social.api_access',
'name' => 'Social API Access',
'description' => 'Access to SocialHost API',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 10,
],
[
'code' => 'social.templates',
'name' => 'Post Templates',
'description' => 'Number of saved post templates',
'category' => 'social',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 11,
],
[
'code' => 'social.hashtag_groups',
'name' => 'Hashtag Groups',
'description' => 'Number of saved hashtag groups',
'category' => 'social',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 12,
],
[
'code' => 'social.ai_suggestions',
'name' => 'AI Content Suggestions',
'description' => 'AI-powered caption generation and content improvement',
'category' => 'social',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 13,
],
// AI features
[
'code' => 'ai.credits',
'name' => 'AI Credits',
'description' => 'AI generation credits per month',
'category' => 'ai',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 1,
],
[
'code' => 'ai.providers.claude',
'name' => 'Claude AI',
'description' => 'Access to Claude AI provider',
'category' => 'ai',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
[
'code' => 'ai.providers.gemini',
'name' => 'Gemini AI',
'description' => 'Access to Gemini AI provider',
'category' => 'ai',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
// Team features
[
'code' => 'team.members',
'name' => 'Team Members',
'description' => 'Number of team members per workspace',
'category' => 'team',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
// API features
[
'code' => 'api.requests',
'name' => 'API Requests',
'description' => 'API requests per 30 days (rolling)',
'category' => 'api',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_ROLLING,
'rolling_window_days' => 30,
'sort_order' => 1,
],
// MCP Quota features
[
'code' => 'mcp.monthly_tool_calls',
'name' => 'MCP Tool Calls',
'description' => 'Monthly limit for MCP tool calls',
'category' => 'mcp',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 1,
],
[
'code' => 'mcp.monthly_tokens',
'name' => 'MCP Tokens',
'description' => 'Monthly limit for MCP token consumption',
'category' => 'mcp',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 2,
],
// Storage - Global pool
[
'code' => 'core.res.storage.total',
'name' => 'Total Storage',
'description' => 'Total storage across all services (MB)',
'category' => 'storage',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
// ─────────────────────────────────────────────────────────────
// lt.hn Pricing Features (numeric - ordered by sort_order)
// ─────────────────────────────────────────────────────────────
[
'code' => 'bio.pages',
'name' => 'Bio Pages',
'description' => 'Number of pages allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 10,
],
[
'code' => 'webpage.sub_pages',
'name' => 'Sub-Pages',
'description' => 'Additional pages under your main page',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 20,
],
[
'code' => 'bio.blocks',
'name' => 'Page Blocks',
'description' => 'Number of blocks per page',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 30,
],
[
'code' => 'bio.static_sites',
'name' => 'Static Websites',
'description' => 'Number of static websites allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 40,
],
[
'code' => 'bio.custom_domains',
'name' => 'Custom Domains',
'description' => 'Number of custom domains allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 50,
],
[
'code' => 'bio.web3_domains',
'name' => 'Web3 Domains',
'description' => 'Number of Web3 domains (ENS, etc.)',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 60,
],
[
'code' => 'bio.vcard',
'name' => 'vCard',
'description' => 'Number of vCard downloads allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 70,
],
[
'code' => 'bio.events',
'name' => 'Events',
'description' => 'Number of event blocks allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 80,
],
[
'code' => 'bio.file_downloads',
'name' => 'File Downloads',
'description' => 'Number of file download blocks allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 90,
],
[
'code' => 'bio.splash_pages',
'name' => 'Splash Pages',
'description' => 'Number of splash/landing pages allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 100,
],
[
'code' => 'bio.shortened_links',
'name' => 'Shortened Links',
'description' => 'Number of shortened links allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 110,
],
[
'code' => 'bio.pixels',
'name' => 'Pixels',
'description' => 'Number of tracking pixels allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 120,
],
[
'code' => 'bio.qr_codes',
'name' => 'QR Codes',
'description' => 'Number of QR codes allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 130,
],
// ─────────────────────────────────────────────────────────────
// lt.hn Pricing Features (boolean - ordered by sort_order)
// ─────────────────────────────────────────────────────────────
[
'code' => 'bio.analytics.basic',
'name' => 'Basic Analytics',
'description' => 'Basic analytics for pages',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 200,
],
[
'code' => 'support.community',
'name' => 'Community Support',
'description' => 'Access to community support',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 210,
],
[
'code' => 'support.host.uk.com',
'name' => 'Support',
'description' => 'Email support access',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 211,
],
[
'code' => 'support.priority',
'name' => 'Priority Support',
'description' => 'Priority support access',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 212,
],
[
'code' => 'bio.themes',
'name' => 'Themes',
'description' => 'Access to page themes',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 220,
],
// ─────────────────────────────────────────────────────────────
// Legacy Bio features (internal use)
// ─────────────────────────────────────────────────────────────
[
'code' => 'bio.shortlinks',
'name' => 'Short Links',
'description' => 'Number of short links allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 150,
],
[
'code' => 'bio.static',
'name' => 'Static Pages',
'description' => 'Number of static HTML pages allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 151,
],
[
'code' => 'bio.domains',
'name' => 'Custom Domains (Legacy)',
'description' => 'Number of custom domains allowed',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 152,
],
[
'code' => 'bio.analytics_days',
'name' => 'Analytics Retention',
'description' => 'Days of analytics history retained',
'category' => 'web',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'bio.tier.pro',
'name' => 'Pro Block Types',
'description' => 'Access to pro-tier block types',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
[
'code' => 'bio.tier.ultimate',
'name' => 'Ultimate Block Types',
'description' => 'Access to ultimate-tier block types',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 7,
],
[
'code' => 'bio.tier.payment',
'name' => 'Payment Block Types',
'description' => 'Access to payment block types',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 8,
],
[
'code' => 'web.themes.premium',
'name' => 'Premium Themes',
'description' => 'Access to premium page themes',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 9,
],
[
'code' => 'bio.pwa',
'name' => 'Progressive Web App',
'description' => 'Turn pages into installable apps',
'category' => 'web',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 230,
],
// Content features (native CMS)
[
'code' => 'content.mcp_access',
'name' => 'Content MCP Access',
'description' => 'Access to content management via MCP tools',
'category' => 'content',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'content.items',
'name' => 'Content Items',
'description' => 'Number of content items (posts, pages)',
'category' => 'content',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
[
'code' => 'content.ai_generation',
'name' => 'AI Content Generation',
'description' => 'Generate content using AI via MCP',
'category' => 'content',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
// Analytics features
[
'code' => 'analytics.sites',
'name' => 'Analytics Sites',
'description' => 'Number of sites to track',
'category' => 'analytics',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'analytics.pageviews',
'name' => 'Monthly Pageviews',
'description' => 'Pageviews tracked per month',
'category' => 'analytics',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 2,
],
// Support features
[
'code' => 'support.mailboxes',
'name' => 'Mailboxes',
'description' => 'Number of support mailboxes',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'support.agents',
'name' => 'Support Agents',
'description' => 'Number of support agents',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
[
'code' => 'support.conversations',
'name' => 'Conversations per Month',
'description' => 'Number of conversations per month',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_MONTHLY,
'sort_order' => 3,
],
[
'code' => 'support.chat_widget',
'name' => 'Live Chat Widget',
'description' => 'Enable live chat widget',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 4,
],
[
'code' => 'support.saved_replies',
'name' => 'Saved Replies',
'description' => 'Number of saved reply templates',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'support.custom_folders',
'name' => 'Custom Folders',
'description' => 'Enable custom folder organisation',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
[
'code' => 'support.api_access',
'name' => 'API Access',
'description' => 'Access to Support API endpoints',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 7,
],
[
'code' => 'support.auto_reply',
'name' => 'Auto Reply',
'description' => 'Automatic reply to incoming messages',
'category' => 'support',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 8,
],
[
'code' => 'support.email_templates',
'name' => 'Email Templates',
'description' => 'Number of email templates',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 9,
],
[
'code' => 'support.file_storage_mb',
'name' => 'File Storage (MB)',
'description' => 'File attachment storage in megabytes',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 10,
],
[
'code' => 'support.retention_days',
'name' => 'Retention Days',
'description' => 'Number of days to retain conversation history',
'category' => 'support',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 11,
],
// Tools features (utility tools access)
[
'code' => 'tool.mcp_access',
'name' => 'Tools MCP Access',
'description' => 'Access to utility tools via MCP API',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 1,
],
[
'code' => 'tool.url_shortener',
'name' => 'URL Shortener',
'description' => 'Create persistent short links with analytics',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 2,
],
[
'code' => 'tool.qr_generator',
'name' => 'QR Code Generator',
'description' => 'Create and save QR codes',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 3,
],
[
'code' => 'tool.dns_lookup',
'name' => 'DNS Lookup',
'description' => 'DNS record lookup tool',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 4,
],
[
'code' => 'tool.ssl_lookup',
'name' => 'SSL Lookup',
'description' => 'SSL certificate lookup tool',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 5,
],
[
'code' => 'tool.whois_lookup',
'name' => 'WHOIS Lookup',
'description' => 'Domain WHOIS lookup tool',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 6,
],
[
'code' => 'tool.ip_lookup',
'name' => 'IP Lookup',
'description' => 'IP address geolocation lookup',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 7,
],
[
'code' => 'tool.http_headers',
'name' => 'HTTP Headers',
'description' => 'HTTP header inspection tool',
'category' => 'tools',
'type' => Feature::TYPE_BOOLEAN,
'reset_type' => Feature::RESET_NONE,
'sort_order' => 8,
],
];
foreach ($features as $featureData) {
Feature::updateOrCreate(
['code' => $featureData['code']],
$featureData
);
}
// Create child features for storage pool
$storageParent = Feature::where('code', 'core.res.storage.total')->first();
if ($storageParent) {
$storageChildren = [
[
'code' => 'core.res.cdn',
'name' => 'Main Site CDN',
'description' => 'CDN storage for main site (MB)',
'category' => 'storage',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'parent_feature_id' => $storageParent->id,
'sort_order' => 2,
],
[
'code' => 'bio.cdn',
'name' => 'Bio CDN',
'description' => 'CDN storage for bio pages (MB)',
'category' => 'storage',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'parent_feature_id' => $storageParent->id,
'sort_order' => 3,
],
[
'code' => 'social.cdn',
'name' => 'Social CDN',
'description' => 'CDN storage for social media (MB)',
'category' => 'storage',
'type' => Feature::TYPE_LIMIT,
'reset_type' => Feature::RESET_NONE,
'parent_feature_id' => $storageParent->id,
'sort_order' => 4,
],
];
foreach ($storageChildren as $childData) {
Feature::updateOrCreate(
['code' => $childData['code']],
$childData
);
}
}
$this->command->info('Features seeded successfully.');
}
}