This commit is contained in:
Mark Gregory
2026-09-30 10:45:45 +01:00
parent 59aa1e1392
commit c045f66256
8 changed files with 335 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
APP_NAME=SonarDesk
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=https://sonardesk.vm
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
# PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="licensing@sonardesk.absdev.net"
MAIL_FROM_NAME="SonarDesk"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
# SonarDesk commercial/licensing
SONARDESK_ENVIRONMENT=develop
SONARDESK_LICENSE_PRIVATE_KEY_PATH=
SONARDESK_LICENSE_PUBLIC_KEY=
SONARDESK_DEFAULT_EDITION=Professional
SONARDESK_DEFAULT_MAX_MAJOR_VERSION=1
SONARDESK_PURCHASE_URL=https://sonardesk.vm/buy
SONARDESK_PORTAL_URL=https://sonardesk.vm/portal
SONARDESK_SUPPORT_URL=https://sonardesk.vm/support
PADDLE_API_KEY=
PADDLE_API_URL=https://sandbox-api.paddle.com
PADDLE_CLIENT_SIDE_TOKEN=
PADDLE_ENVIRONMENT=sandbox
PADDLE_WEBHOOK_SECRET=
PADDLE_WEBHOOK_TOLERANCE=300
PADDLE_PRODUCT_ID=
PADDLE_PERSONAL_MONTHLY_PRICE_ID=
PADDLE_PERSONAL_ANNUAL_PRICE_ID=
PADDLE_PROFESSIONAL_MONTHLY_PRICE_ID=
PADDLE_PROFESSIONAL_ANNUAL_PRICE_ID=
LEMON_SQUEEZY_WEBHOOK_SECRET=
+87
View File
@@ -0,0 +1,87 @@
APP_NAME=SonarDesk
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://sonardsk.absdev.net
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
# PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=CHANGE_ME
MAIL_PORT=587
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="licensing@sonardesk.absdev.net"
MAIL_FROM_NAME="SonarDesk"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
# SonarDesk commercial/licensing
SONARDESK_ENVIRONMENT=production
SONARDESK_LICENSE_PRIVATE_KEY_PATH=
SONARDESK_LICENSE_PUBLIC_KEY=
SONARDESK_DEFAULT_EDITION=Professional
SONARDESK_DEFAULT_MAX_MAJOR_VERSION=1
SONARDESK_PURCHASE_URL=https://sonardsk.absdev.net/buy
SONARDESK_PORTAL_URL=https://sonardsk.absdev.net/portal
SONARDESK_SUPPORT_URL=https://sonardsk.absdev.net/support
PADDLE_API_KEY=
PADDLE_API_URL=https://api.paddle.com
PADDLE_CLIENT_SIDE_TOKEN=
PADDLE_ENVIRONMENT=production
PADDLE_WEBHOOK_SECRET=
PADDLE_WEBHOOK_TOLERANCE=300
PADDLE_PRODUCT_ID=
PADDLE_PERSONAL_MONTHLY_PRICE_ID=
PADDLE_PERSONAL_ANNUAL_PRICE_ID=
PADDLE_PROFESSIONAL_MONTHLY_PRICE_ID=
PADDLE_PROFESSIONAL_ANNUAL_PRICE_ID=
LEMON_SQUEEZY_WEBHOOK_SECRET=
+87
View File
@@ -0,0 +1,87 @@
APP_NAME=SonarDesk
APP_ENV=staging
APP_KEY=
APP_DEBUG=false
APP_URL=https://sonardesk.stage.absdev.net
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
# PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=CHANGE_ME
MAIL_PORT=587
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="licensing@sonardesk.absdev.net"
MAIL_FROM_NAME="SonarDesk"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
# SonarDesk commercial/licensing
SONARDESK_ENVIRONMENT=stage
SONARDESK_LICENSE_PRIVATE_KEY_PATH=
SONARDESK_LICENSE_PUBLIC_KEY=
SONARDESK_DEFAULT_EDITION=Professional
SONARDESK_DEFAULT_MAX_MAJOR_VERSION=1
SONARDESK_PURCHASE_URL=https://sonardesk.stage.absdev.net/buy
SONARDESK_PORTAL_URL=https://sonardesk.stage.absdev.net/portal
SONARDESK_SUPPORT_URL=https://sonardesk.stage.absdev.net/support
PADDLE_API_KEY=
PADDLE_API_URL=https://sandbox-api.paddle.com
PADDLE_CLIENT_SIDE_TOKEN=
PADDLE_ENVIRONMENT=sandbox
PADDLE_WEBHOOK_SECRET=
PADDLE_WEBHOOK_TOLERANCE=300
PADDLE_PRODUCT_ID=
PADDLE_PERSONAL_MONTHLY_PRICE_ID=
PADDLE_PERSONAL_ANNUAL_PRICE_ID=
PADDLE_PROFESSIONAL_MONTHLY_PRICE_ID=
PADDLE_PROFESSIONAL_ANNUAL_PRICE_ID=
LEMON_SQUEEZY_WEBHOOK_SECRET=
@@ -0,0 +1,20 @@
<?php
namespace App\Console\Commands;
use App\Services\Licensing\LicenseDeliveryService;
use Illuminate\Console\Command;
final class SonarDeskLicenseDeliver extends Command
{
protected $signature = 'sonardesk:license-deliver {--limit=50 : Maximum pending licence emails to send}';
protected $description = 'Deliver pending SonarDesk licence-key emails';
public function handle(LicenseDeliveryService $delivery): int
{
$limit = max(1, min((int) $this->option('limit'), 100));
$count = $delivery->deliverPending($limit);
$this->info("Delivered {$count} licence email(s).");
return self::SUCCESS;
}
}
+11
View File
@@ -0,0 +1,11 @@
## Licensing/email release checks
- Production app endpoint: `https://sonardsk.absdev.net`.
- Stage app endpoint: `https://sonardesk.stage.absdev.net`.
- Production must use Paddle production credentials and the production webhook destination.
- `MAIL_MAILER` must be a real delivery transport in production; never `log`.
- Run the Laravel scheduler continuously so pending licence-key emails retry automatically.
- Verify `php artisan sonardesk:license-deliver` reports no unexpected pending delivery failures.
- Verify a real Paddle purchase creates one licence, sends one key email, activates a clean Mac, validates after relaunch, and deactivates from the portal.
- Never deploy `.env`, signing seeds, Paddle secrets, or webhook secrets from source control.
@@ -0,0 +1,20 @@
SonarDesk — Your licence is ready
{{ $customerName ? 'Hello '.$customerName.',' : 'Hello,' }}
Thank you for choosing SonarDesk. Your {{ $edition }} licence key is:
{{ $licenseKey }}
To activate:
1. Open SonarDesk.
2. Open Settings → Licence.
3. Paste the key above and select Activate.
@if($expiresAt)Current entitlement period: {{ $expiresAt->format('j M Y') }}.
@endif
@if($portalUrl)Manage your licence: {{ $portalUrl }}
@endif
Keep this key private.
@@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Your SonarDesk licence key</title></head>
<body style="margin:0;background:#f4f6f8;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:#172033">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background:#f4f6f8;padding:32px 12px"><tr><td align="center">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="max-width:620px;background:#fff;border:1px solid #e4e8ee;border-radius:16px;overflow:hidden">
<tr><td style="padding:30px 34px;background:#111827;color:#fff"><div style="font-size:24px;font-weight:700">SonarDesk</div><div style="margin-top:5px;color:#cbd5e1">Your licence is ready</div></td></tr>
<tr><td style="padding:34px">
<p style="margin:0 0 18px">{{ $customerName ? 'Hello '.$customerName.',' : 'Hello,' }}</p>
<p style="margin:0 0 22px;line-height:1.6">Thank you for choosing SonarDesk. Your {{ $edition }} licence key is:</p>
<div style="padding:18px;border:1px solid #d7dde5;border-radius:10px;background:#f8fafc;text-align:center;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:21px;font-weight:700;letter-spacing:1px">{{ $licenseKey }}</div>
<p style="margin:24px 0 10px;line-height:1.6"><strong>Activate SonarDesk</strong></p>
<ol style="padding-left:22px;line-height:1.8;margin-top:0"><li>Open SonarDesk on your Mac.</li><li>Open <strong>Settings → Licence</strong>.</li><li>Paste the licence key above and select <strong>Activate</strong>.</li></ol>
@if($expiresAt)<p style="line-height:1.6">Current entitlement period: <strong>{{ $expiresAt->format('j M Y') }}</strong>.</p>@endif
@if($portalUrl)<p style="margin:24px 0"><a href="{{ $portalUrl }}" style="display:inline-block;background:#2563eb;color:#fff;text-decoration:none;padding:12px 18px;border-radius:8px;font-weight:600">Manage your licence</a></p>@endif
<p style="margin:22px 0 0;color:#64748b;font-size:13px;line-height:1.6">Keep this key private. If you did not make this purchase, contact SonarDesk support.</p>
</td></tr></table>
</td></tr></table>
</body></html>
+4
View File
@@ -0,0 +1,4 @@
cloudflared tunnel \
--url https://sonardesk.vm \
--no-tls-verify \
--http-host-header sonardesk.vm