move into sonardesk
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# ABSDev / SonarDesk integration — development scaffold
|
||||
|
||||
**NOT PRODUCTION READY. DO NOT DEPLOY OVER AN EXISTING LICENSING SERVER.**
|
||||
|
||||
Implemented:
|
||||
- Preserved ABSDev application as base.
|
||||
- Added SonarDesk-host-specific marketing routes and responsive ABSDev-inspired navy/gold views.
|
||||
- Archived licensing source under `integration/sonardesk-legacy/` for a controlled migration. This directory is **not** wired into runtime.
|
||||
|
||||
Not implemented / not verified:
|
||||
- Licensing API, existing download/appcast routes, payment checkout/webhooks, customer identity mapping, backend administration, data migrations and theme-manager integration.
|
||||
- Laravel test suite, browser tests, PHP dependencies and deployment verification.
|
||||
|
||||
**Important:** Existing unscoped ABSDev routes and module routes may still collide with the SonarDesk host. The new domain routes are only an initial frontend scaffold. Do not point production SonarDesk DNS at this build.
|
||||
|
||||
Next steps: inventory and namespace every licensing route, reconcile User schema and Fortify authentication, port modules and database migrations without collisions, wire checkout and webhooks, add regression tests, and test on staging with anonymised production data.
|
||||
@@ -6,4 +6,5 @@ use App\Providers\FortifyServiceProvider;
|
||||
return [
|
||||
AppServiceProvider::class,
|
||||
FortifyServiceProvider::class,
|
||||
\Modules\Licensing\Providers\IntegratedLicensingServiceProvider::class,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Phase 2: route-contract baseline (not a runtime migration)
|
||||
|
||||
This iteration adds a repeatable **static** route inventory (`sonardesk-route-inventory.json`), its regeneration script (`php scripts/integration/audit_routes.php`) and host-level marketing route tests.
|
||||
|
||||
## Production blockers
|
||||
|
||||
1. Extract legacy API routes from module route providers and compare the **runtime** `php artisan route:list --json` outputs of both original applications. Static regex is not a substitute for runtime route enumeration.
|
||||
2. Port licensing models, migrations, services, controllers and commands with namespace isolation. Do not run legacy migrations against the ABSDev database until table/schema conflicts have been reviewed.
|
||||
3. Reconcile Fortify/Spatie auth with legacy users, permissions, sessions and licence ownership.
|
||||
4. Integrate Paddle/Lemon Squeezy webhook signature verification and idempotency, preserve existing endpoints and secrets outside source control.
|
||||
5. Port downloads, appcast, support and release-management views/controllers into Stylist's SonarDesk theme.
|
||||
6. Test with a staging database copy and synthetic payment events; only then switch DNS.
|
||||
|
||||
No legacy licensing endpoints have been activated by this change. The archived legacy source remains isolated.
|
||||
@@ -0,0 +1,391 @@
|
||||
{
|
||||
"generated_from": "archived SonarDesk source",
|
||||
"warning": "Static extraction: nested prefixes, resource routes and dynamic registrations require runtime verification",
|
||||
"routes": [
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/activate",
|
||||
"source": "modules/Licensing/Routes/api.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/validate",
|
||||
"source": "modules/Licensing/Routes/api.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/deactivate",
|
||||
"source": "modules/Licensing/Routes/api.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/webhooks/{provider}",
|
||||
"source": "modules/Licensing/Routes/api.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/licences/{license}",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/licences/{license}/upgrade",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/licences/{license}/subscription",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/licences/{license}/resend",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/licences/{license}/activations/{activation}",
|
||||
"source": "modules/Licensing/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/buy",
|
||||
"source": "modules/Paddle/Routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/sitemap.xml",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{key}.txt",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/robots.txt",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/release",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/downloads/sonardesk/details",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/download",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/downloads/products/{product}/details",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/downloads/products/{product}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/downloads/{release}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/updates/appcast.xml",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/support",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/support",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/login",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/login",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/register",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/register",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/forgot-password",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/forgot-password",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/reset-password/{token}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/reset-password",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/logout",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/verify-email",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/verify-email/{id}/{hash}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/email/verification-notification",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/licences",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/licences/{license}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/licences/{license}/revoke",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/licences/{license}/restore",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/users",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/users/{user}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/users/{user}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/users/{user}/verify",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/users/{user}/verification-email",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/users/{user}/password-reset",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/users/{user}/suspend",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/users/{user}/restore",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/users/{user}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/users/{user}/licences/{license}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/users/{user}/licences/{license}/activations/{activation}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/seo",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/seo",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/cms",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/cms/create",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/cms",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/cms/{page}/edit",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/cms/{page}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/cms/{page}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/download-products",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/download-products",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/download-products/{product}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/download-products/{product}/publication",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/download-products/{product}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/releases",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/releases/create",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/releases",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/releases/settings",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/releases/settings",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/releases/{release}/edit",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/releases/{release}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/releases/{release}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/support",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/support/{ticket}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "PATCH",
|
||||
"path": "/support/{ticket}",
|
||||
"source": "routes/web.php"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/pages/{slug}",
|
||||
"source": "routes/web.php"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/** Static legacy route inventory; does not boot either application or require secrets. */
|
||||
$root = dirname(__DIR__, 2);
|
||||
$legacy = $root.'/integration/sonardesk-legacy';
|
||||
$files = glob($legacy.'/routes/*.php');
|
||||
foreach (glob($legacy.'/modules/*/Routes/*.php') ?: [] as $file) $files[] = $file;
|
||||
foreach (glob($legacy.'/modules/*/routes/*.php') ?: [] as $file) $files[] = $file;
|
||||
sort($files);
|
||||
$inventory = [];
|
||||
foreach ($files as $file) {
|
||||
$contents = file_get_contents($file);
|
||||
preg_match_all('/Route::(get|post|put|patch|delete|match|any)\s*\(\s*[\'\"]([^\'\"]+)/', $contents, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $m) $inventory[] = ['method'=>strtoupper($m[1]), 'path'=>$m[2], 'source'=>substr($file, strlen($legacy)+1)];
|
||||
}
|
||||
$out = $root.'/integration/sonardesk-route-inventory.json';
|
||||
file_put_contents($out, json_encode(['generated_from'=>'archived SonarDesk source','warning'=>'Static extraction: nested prefixes, resource routes and dynamic registrations require runtime verification','routes'=>$inventory], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."\n");
|
||||
fwrite(STDOUT, count($inventory)." static route declarations written to $out\n");
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Integration;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
class SonarDeskDomainRoutingTest extends TestCase
|
||||
{
|
||||
public function test_sonardesk_hosts_resolve_the_product_homepage(): void
|
||||
{
|
||||
foreach (['sonardesk.absdev.net', 'sonardesk.co.uk', 'www.sonardesk.co.uk'] as $host) {
|
||||
$this->get('https://'.$host.'/')->assertOk()->assertSee('SonarDesk');
|
||||
}
|
||||
}
|
||||
|
||||
public function test_product_features_and_pricing_are_available_on_each_host(): void
|
||||
{
|
||||
foreach (['sonardesk.absdev.net', 'sonardesk.co.uk', 'www.sonardesk.co.uk'] as $host) {
|
||||
$this->get('https://'.$host.'/features')->assertOk();
|
||||
$this->get('https://'.$host.'/pricing')->assertOk();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user