diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 86caf3d..0692f36 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,7 +2,21 @@ "permissions": { "allow": [ "WebSearch", - "Bash(ls:*)" + "Bash(ls:*)", + "WebFetch(domain:lowendbox.com)", + "WebFetch(domain:www.lowendtalk.com)", + "Bash(php artisan tinker:*)", + "WebFetch(domain:www.vultr.com)", + "WebFetch(domain:www.digitalocean.com)", + "WebFetch(domain:www.linode.com)", + "Bash(vendor/bin/pint:*)", + "Bash(php artisan make:request:*)", + "Bash(php artisan make:controller:*)", + "Bash(php artisan make:test:*)", + "Bash(php artisan test:*)", + "Bash(npm run build:*)" ] - } + }, + "outputStyle": "default", + "spinnerTipsEnabled": false } diff --git a/CLAUDE.md b/CLAUDE.md index eedd61c..bc2a395 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -42,17 +42,18 @@ The Laravel application is in **`website/`**. All artisan, composer, and npm com ``` website/ ├── app/ -│ ├── Models/ # 14 Eloquent models +│ ├── Models/ # 14 Eloquent models (Service uses SoftDeletes) │ ├── Http/Controllers/ # Account/ and Admin/ controllers │ ├── Services/Billing/ # BillingServiceInterface, Stripe, PayPal, Dunning │ ├── Events/ # PaymentSucceeded/Failed, SubscriptionCreated/Cancelled │ ├── Listeners/ # HandlePaymentSucceeded/Failed +│ ├── Console/Commands/ # RetryProvisioningCommand, SyncStripePrices │ └── Providers/ # AppServiceProvider, FortifyServiceProvider ├── bootstrap/app.php # Middleware, exceptions, routing (Laravel 12 style) ├── config/ # App, auth, fortify, passport, cashier, paypal, permission ├── database/ -│ ├── migrations/ # 30 migrations (15 custom + defaults + packages) -│ ├── factories/ # 7 factories +│ ├── migrations/ # 44 migrations +│ ├── factories/ # 8 factories │ └── seeders/ # Roles, plans, admin user ├── resources/ │ ├── ts/ # TypeScript source (migrated from js/) @@ -65,7 +66,7 @@ website/ │ │ ├── @layouts/ # Layout SCSS stubs for Vuexy compatibility │ │ ├── Layouts/ # AccountLayout, AdminLayout, AuthLayout, MarketingLayout │ │ ├── Components/ # FlashMessages, StatCard, StatusChip, ThemeSwitcher, app-form-elements/ -│ │ └── Pages/ # Auth/ (7), Profile/ (2), Plans/ (2), Checkout/ (1), Subscriptions/ (2), Billing/ (3), Admin/ (1), Marketing/ (9), Dashboard +│ │ └── Pages/ # Auth/ (7), Profile/ (2), Plans/ (1), Checkout/ (1), Subscriptions/ (2), Billing/ (3), Services/ (2), Tickets/ (3), Admin/ (25+), Marketing/ (13), Dashboard │ ├── styles/ # SCSS with Vuexy @core overrides │ │ ├── @core/ # Copied from Vuexy: base + template SCSS overrides │ │ ├── variables/ # _vuetify.scss, _template.scss @@ -73,7 +74,7 @@ website/ │ ├── images/ │ └── views/app.blade.php # Inertia root template ├── routes/ # web.php, account.php, admin.php, marketing.php, webhooks.php, api.php -├── tests/ # 53 Pest tests (Phase 1 + Phase 2) +├── tests/ # 252 Pest tests passing (1310 assertions) ├── composer.json ├── package.json └── vite.config.js @@ -83,12 +84,13 @@ website/ - **Framework:** Laravel 12 (PHP 8.3), Laravel 12 slim structure (no Kernel files) - **Frontend:** Vue 3 + Inertia.js v2 + TypeScript (REQUIRED) + Vuetify 3 (Vuexy design system) + Vite 7 - **UI Theme:** Vuexy Vue + Laravel Admin Dashboard — SCSS overrides from @core integrated, AppTextField/AppSelect/AppTextarea wrapper components, purple primary (#7367F0) -- **Testing:** Pest 4 + PHPUnit 12 +- **Testing:** Pest 4 + PHPUnit 12 (252 tests, 1310 assertions) - **Formatting:** Laravel Pint - **Payments:** Laravel Cashier (Stripe) + srmklive/paypal (PayPal) - **Database:** MySQL 8.x, Redis for cache/queue/sessions - **Auth:** Laravel Fortify (login, register, 2FA, password reset, email verify) + Passport (OAuth2/SSO) - **Roles:** spatie/laravel-permission (admin, customer) +- **Queue:** Laravel Horizon for queue management ## Commands ```bash @@ -188,6 +190,9 @@ Always maximize use of subagents (Task tool) to reduce context usage in the main - **Background agents**: Use `run_in_background: true` for long-running tasks that don't block other work. Check results later with the Read tool on the output file. - **Batch similar work**: If updating 10+ files with the same pattern, send them to an agent rather than editing each one in the main context. +### Frontend Design Skill +When using the `frontend-design` skill, **ALWAYS** run it in the background using `run_in_background: true`. Never run it in the main context window — it consumes significant context and produces large outputs. Check its output file when complete using the Read tool. + ### Headless Chrome Chrome is available for visual testing and screenshot comparison. Use it to verify UI matches design references. ```bash @@ -259,7 +264,7 @@ google-chrome --headless=new --disable-gpu --no-sandbox --screenshot=/tmp/screen ## Key Business Domains 1. **Billing** — Subscriptions, invoices, payments (Stripe + PayPal), dunning, coupons -2. **Provisioning** — VirtFusion (VPS), Pterodactyl (Game), SynergyCP (Dedicated), Enhance (Hosting) +2. **Provisioning** — VirtFusion (VPS), Pterodactyl (Game), SynergyCP (Dedicated), Enhance (Hosting) — idempotent provisioning with retry 3. **Customer Management** — Profiles, support tickets, notifications 4. **Admin Panel** — Dashboard, analytics, user/service management 5. **SSO** — Single sign-on via Laravel Passport diff --git a/PROJECT_DEVELOPMENT.md b/PROJECT_DEVELOPMENT.md index 6a9778b..ccf1bc5 100644 --- a/PROJECT_DEVELOPMENT.md +++ b/PROJECT_DEVELOPMENT.md @@ -12,7 +12,7 @@ Replace WHMCS with a custom Laravel 12 application for managing EZSCALE Hosting' - **Dedicated Servers:** SynergyCP - **Web Hosting:** Enhance (https://enhance.com/) - **Container Management:** Portainer (for BFACP deployment) -- **Support System:** SupportPal (ticketing) +- **Support System:** Standalone ticket system (built-in, replaced SupportPal) - **Network:** Juniper switches with VLANs (dedicated customers, corporate, hypervisors) - **Bandwidth Monitoring:** ElastiFlow (NetFlow/sFlow collector) @@ -55,9 +55,9 @@ Replace WHMCS with a custom Laravel 12 application for managing EZSCALE Hosting' │ │ │ │ │ │ Enhance │ │ │ │ │ └──────────┘ └──────────┘ └──────────────┘ └───────────────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌───────────────────┐ │ -│ │SupportPal│ │Analytics │ │ Customer │ │ Admin Tools │ │ -│ │Integration│ │Dashboard │ │ API │ │ Full Control │ │ -│ │SSO+Tickets│ │MRR/Churn │ │ │ │ │ │ +│ │ Tickets │ │Analytics │ │ Customer │ │ Admin Tools │ │ +│ │ System │ │Dashboard │ │ API │ │ Full Control │ │ +│ │Standalone│ │MRR/Churn │ │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────────┘ └───────────────────┘ │ ├─────────────────────────────────────────────────────────────────────┤ │ MySQL 8.x (Multi-region) │ Redis (Queue/Cache/Session) │ @@ -65,8 +65,8 @@ Replace WHMCS with a custom Laravel 12 application for managing EZSCALE Hosting' │ │ ┌────┴────────┬──────────┬───────────┬───┴────┬─────────────┐ │ │ │ │ │ │ -VirtFusion Pterodactyl SynergyCP Enhance SupportPal ElastiFlow - API API API API API API +VirtFusion Pterodactyl SynergyCP Enhance ElastiFlow + API API API API API ``` ## 4. Key Design Decisions @@ -82,7 +82,7 @@ VirtFusion Pterodactyl SynergyCP Enhance SupportPal ElastiFlow - **Billing Architecture:** `BillingServiceInterface` abstracts Stripe and PayPal for gateway-agnostic code ### Frontend & Auth (DECIDED) -- **Stack:** Vue 3 + Inertia.js + Tailwind CSS (Laravel 12 Vue starter kit) +- **Stack:** Vue 3 + Inertia.js v2 + TypeScript + Vuetify 3 (Vuexy design system) - **UI Theme:** **Vuexy** VueJS + Laravel Admin Dashboard Template - Purchase: https://themeforest.net/item/vuexy-vuejs-html-laravel-admin-dashboard-template/23328599 - Demo: https://pixinvent.com/vuexy-vuejs-laravel-admin-template/ @@ -123,12 +123,13 @@ All service provisioning is **fully automated** via API on successful payment: - **No Add-ons:** Automatic overage billing only (no one-time bandwidth add-ons) ### Support Integration (DECIDED) -- **System:** SupportPal (external ticketing system) -- **Integration Level:** Full integration - - SSO for seamless access - - View recent tickets in billing dashboard - - Create tickets from billing panel via SupportPal API - - Full ticket history accessible to customers +- **System:** Standalone ticket system (built-in, no external dependencies) +- **Features:** + - Full ticket CRUD with replies for customers and admins + - Email integration (IMAP polling via webklex/php-imap) + - Ticket references: [EZSCALE-{id}] format with email threading + - Departments, priorities, statuses + - 42 Pest tests for ticket system - **Discord:** Admin notifications via webhook (new orders, failures, cancellations, high revenue) ### Customer Features (DECIDED) @@ -295,20 +296,21 @@ bandwidth_usage ├── timestamps ``` -### Support (SupportPal Integration) +### Support (Standalone Ticket System) ``` -support_tickets (mirrored from SupportPal via webhooks) +support_tickets ├── id, user_id -├── supportpal_ticket_id -├── subject, status (open, closed, pending) +├── reference (e.g., EZSCALE-001) +├── subject, status (open, closed, pending, in_progress) ├── priority (low, medium, high, urgent) +├── department ├── last_reply_at ├── timestamps -announcements -├── id, title, content (HTML) -├── type (maintenance, feature, outage) -├── published_at, expires_at +ticket_replies +├── id, ticket_id, user_id +├── body (text) +├── is_staff_reply (boolean) ├── timestamps ``` @@ -364,17 +366,13 @@ announcements **Service:** `App\Services\Monitoring\BandwidthService` -### 6.6 SupportPal API (Ticket System) -**Endpoints needed:** -- `GET /api/ticket/{id}` - Get ticket details -- `GET /api/ticket/user/{user_id}` - Get user's tickets -- `POST /api/ticket` - Create new ticket -- `POST /api/ticket/{id}/reply` - Reply to ticket -- `GET /api/ticket/{id}/replies` - Get ticket thread - -**SSO Implementation:** SupportPal supports SAML or custom SSO - use Laravel Passport tokens - -**Service:** `App\Services\Support\SupportPalService` +### 6.6 Standalone Ticket System (Built-in) +**No external integration needed.** Tickets are managed natively: +- Customer and Admin controllers with full CRUD +- Email integration via IMAP polling (webklex/php-imap) +- Email threading with Message-ID, In-Reply-To, References headers +- Ticket reference format: [EZSCALE-{id}] +- Scheduled: `tickets:process-emails` runs every 2 minutes ### 6.7 Email Notifications (Mailgun/SendGrid) **Laravel Notifications for:** @@ -494,12 +492,12 @@ announcements - Automatic overage billing - Admin bandwidth reports -### Phase 7: SupportPal Integration -- SSO implementation (Laravel Passport + SupportPal) -- Ticket viewing in customer dashboard -- Ticket creation via SupportPal API -- Webhook handlers for ticket updates -- Discord notifications for new tickets +### Phase 7: Support Ticket System ✓ +- Standalone ticket system with TicketReply model (no external dependencies) +- Customer and admin Vue pages (5 pages total) +- Email integration via IMAP polling (webklex/php-imap) +- Email threading with ticket references [EZSCALE-{id}] +- 42 Pest tests ### Phase 8: Marketing Frontend (ezscale.cloud) - Product catalog pages (VPS, Dedicated, Hosting, Game Servers) @@ -561,7 +559,7 @@ announcements - [x] Frontend stack: Vue 3 + Inertia.js - [x] Infrastructure: VirtFusion, Pterodactyl, SynergyCP, Enhance - [x] Bandwidth monitoring: ElastiFlow (NetFlow/sFlow) -- [x] Support system: SupportPal with full integration +- [x] Support system: Standalone ticket system (built-in) - [x] Domain structure: ezscale.cloud / account / admin - [x] Hosting: Own infrastructure with full DB redundancy - [x] CI/CD: GitHub Actions with staging environment @@ -578,7 +576,6 @@ announcements - [ ] Tax calculation approach: TaxJar/Avalara integration vs manual tax rates? - [ ] Email service final choice: Mailgun or SendGrid? - [ ] Admin panel subdomain: admin.ezscale.cloud or something less obvious for security? -- [ ] Dedicated server semi-automation: How to handle limited hardware inventory (waitlist, manual approval)? - [ ] NetFlow/sFlow deployment: Timeline for switching Juniper to flow exports? - [x] ~~Customer portal theme/branding~~ **DECIDED: Vuexy VueJS + Laravel Admin Dashboard Template** @@ -586,9 +583,9 @@ announcements | Layer | Technology | |-------|------------| -| **Framework** | Laravel 12 (PHP 8.2+) | -| **Frontend** | Vue 3 + Inertia.js + Tailwind CSS | -| **UI Theme** | Vuexy VueJS + Laravel Admin Dashboard | +| **Framework** | Laravel 12 (PHP 8.3) | +| **Frontend** | Vue 3 + Inertia.js v2 + TypeScript + Vuetify 3 | +| **UI Theme** | Vuexy design system (SCSS overrides + Vuetify components) | | **Database** | MySQL 8.x (multi-region replication) | | **Cache/Queue** | Redis | | **Payments** | Laravel Cashier Stripe v16 + srmklive/laravel-paypal | @@ -600,5 +597,5 @@ announcements | **CI/CD** | GitHub Actions | | **Monitoring** | ElastiFlow (bandwidth), Laravel Telescope (debugging) | | **Provisioning APIs** | VirtFusion, Pterodactyl, SynergyCP, Enhance | -| **Support** | SupportPal (external integration) | +| **Support** | Standalone ticket system (built-in) | | **Notifications** | Laravel Notifications + Discord webhooks | diff --git a/TASKS.md b/TASKS.md index 61461dc..d70e34e 100644 --- a/TASKS.md +++ b/TASKS.md @@ -61,7 +61,7 @@ - [x] Create 9 marketing pages (Home, Products, VPS, Dedicated, Web, Game, Pricing, About, Contact) - [x] Create navigation configs (account.ts, admin.ts, marketing.ts) - [x] Set purple primary color (#7367F0) matching Vuexy demo -- [x] All 114 tests passing, build clean (Phase 1-5 + Frontend + Notifications) +- [x] 252 tests passing, 1310 assertions (12 pre-existing VpsControllerTest failures) ## Notifications System ✅ - [x] Create notification classes (PaymentSucceeded, PaymentFailed, SubscriptionCreated, SubscriptionCancelled, ServiceProvisioned, InvoiceGenerated) @@ -72,7 +72,7 @@ - [x] FlashMessages supports info alerts - [x] Inertia shared data includes impersonation state -## Phase 3: Provisioning Automation +## Phase 3: Provisioning Automation ✅ - [x] Create `ProvisioningServiceInterface` abstraction - [x] Build VirtFusion provisioning service: - [x] Create VPS via API @@ -99,6 +99,8 @@ - [x] Build provisioning failure handling and retry logic - [x] Send credentials email on successful provisioning - [x] Log all provisioning actions to `provisioning_logs` table +- [x] Idempotent provisioning (Service::firstOrCreate to prevent duplicates on retry) +- [x] Provisioning retry command (provisioning:retry scheduled every 5 minutes) ## Support Ticket System (Standalone) ✅ - [x] TicketReply model with relationships @@ -114,7 +116,7 @@ - [x] TypeScript interfaces for SupportTicket and TicketReply - [x] Navigation items for both account and admin sidebars - [x] Routes for both account and admin subdomains -- [x] 30 Pest tests (144 total, 775 assertions) +- [x] 42 Pest tests for tickets (252 total, 1310 assertions) ## Phase 4: Customer Dashboard (account.ezscale.cloud) - [x] Build service overview dashboard: @@ -166,20 +168,21 @@ - [x] Terminate service - [ ] Modify service (change plan, extend expiry) - [x] View provisioning logs + - [x] Archive/restore services (soft-delete with SoftDeletes trait) - [x] Order management: - [x] Pending orders list - [x] Approve/reject orders (for semi-automated provisioning) - [x] View order details - [x] Invoice management: - [x] All invoices list (filter by status, date, customer) - - [ ] Create manual invoice - - [ ] Edit invoice (before sending) + - [x] Create manual invoice + - [x] Edit invoice (before sending) - [x] Void/refund invoice - - [ ] Resend invoice email + - [x] Resend invoice email - [x] Coupon management: - [x] Create coupon (percentage, fixed, applies to plans) - [x] Edit coupon details - - [ ] View redemption history + - [x] View redemption history - [x] Deactivate/delete coupon - [x] Plan management: - [x] Create new plan (set pricing, features, billing cycle) @@ -196,7 +199,7 @@ - [x] Audit log viewer: - [x] Filter by user, action, date - [ ] View changes (before/after state) - - [ ] Export logs + - [x] Export logs ## Phase 6: Bandwidth Monitoring & Billing - [ ] Set up NetFlow/sFlow export from Juniper switches @@ -232,6 +235,9 @@ - [x] Game server hosting page with supported games - [x] Pricing page: - [x] Interactive plan comparison table + - [x] Billing cycle toggle (monthly/quarterly/semi-annual/annual) + - [x] Service type tabs with per-type feature display + - [x] Popular/Best Value badges on plans - [ ] Currency selector (USD, EUR, GBP) - [ ] Coupon code application - [ ] Add to cart / checkout flow diff --git a/website/.claude/skills/inertia-vue-development/SKILL.md b/website/.claude/skills/inertia-vue-development/SKILL.md new file mode 100644 index 0000000..4f83849 --- /dev/null +++ b/website/.claude/skills/inertia-vue-development/SKILL.md @@ -0,0 +1,406 @@ +--- +name: inertia-vue-development +description: >- + Develops Inertia.js v2 Vue client-side applications. Activates when creating + Vue pages, forms, or navigation; using ,