php-tenant/Database/Seeders/FeatureSeeder.php
Snider d0ad2737cb refactor: rename namespace from Core\Mod\Tenant to Core\Tenant
Simplifies the namespace hierarchy by removing the intermediate Mod
segment. Updates all 118 files including models, services, controllers,
middleware, tests, and composer.json autoload configuration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 16:30:46 +00:00

901 lines
36 KiB
PHP

<?php
namespace Core\Tenant\Database\Seeders;
use Core\Tenant\Models\Feature;
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.');
}
}